mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
nvethernet: delete old skb for tx TS
Remove SKB for which HW timestamps are not present Bug 3647934 Change-Id: Ib3a5ca6275f74425f4fe43a87ea6696823aedd96 Signed-off-by: Rakesh Goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2716400 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
d38959ba90
commit
118cdcebdc
@@ -130,6 +130,11 @@
|
|||||||
*/
|
*/
|
||||||
#define TS_MISS_THRESHOLD 200U
|
#define TS_MISS_THRESHOLD 200U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC to MSEC converter
|
||||||
|
*/
|
||||||
|
#define ETHER_SECTOMSEC 1000U
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Ethernet clk rates
|
* @brief Ethernet clk rates
|
||||||
*/
|
*/
|
||||||
@@ -388,6 +393,8 @@ struct ether_tx_ts_skb_list {
|
|||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
/** packet id to identify timestamp */
|
/** packet id to identify timestamp */
|
||||||
unsigned int pktid;
|
unsigned int pktid;
|
||||||
|
/** SKB jiffies to find time */
|
||||||
|
unsigned long pkt_jiffies;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,84 @@
|
|||||||
|
|
||||||
#include "ether_linux.h"
|
#include "ether_linux.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ether_get_free_tx_ts_node - get free node for pending SKB
|
||||||
|
*
|
||||||
|
* Algorithm:
|
||||||
|
* - Find index of statically allocayted free memory for pending SKB
|
||||||
|
*
|
||||||
|
* @param[in] pdata: OSD private data structure.
|
||||||
|
*
|
||||||
|
* @retval index number
|
||||||
|
*/
|
||||||
|
static inline unsigned int ether_get_free_tx_ts_node(struct ether_priv_data *pdata)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ETHER_MAX_PENDING_SKB_CNT; i++) {
|
||||||
|
if (pdata->tx_ts_skb[i].in_use == OSI_NONE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_skb_node(struct ether_priv_data *pdata, struct sk_buff *skb,
|
||||||
|
unsigned int pktid) {
|
||||||
|
struct list_head *head_node, *temp_head_node;
|
||||||
|
struct ether_tx_ts_skb_list *pnode = NULL;
|
||||||
|
unsigned int idx;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long now_jiffies = jiffies;
|
||||||
|
|
||||||
|
if (list_empty(&pdata->tx_ts_skb_head)) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&pdata->txts_lock, flags);
|
||||||
|
list_for_each_safe(head_node, temp_head_node,
|
||||||
|
&pdata->tx_ts_skb_head) {
|
||||||
|
pnode = list_entry(head_node,
|
||||||
|
struct ether_tx_ts_skb_list,
|
||||||
|
list_head);
|
||||||
|
|
||||||
|
if ((jiffies_to_msecs(now_jiffies) - jiffies_to_msecs(pnode->pkt_jiffies))
|
||||||
|
>= ETHER_SECTOMSEC) {
|
||||||
|
dev_dbg(pdata->dev, "%s() skb %p deleting for pktid = %x time=%lu\n",
|
||||||
|
__func__, pnode->skb, pnode->pktid, pnode->pkt_jiffies);
|
||||||
|
if (pnode->skb != NULL) {
|
||||||
|
dev_consume_skb_any(pnode->skb);
|
||||||
|
}
|
||||||
|
list_del(head_node);
|
||||||
|
pnode->in_use = OSI_DISABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raw_spin_unlock_irqrestore(&pdata->txts_lock, flags);
|
||||||
|
empty:
|
||||||
|
raw_spin_lock_irqsave(&pdata->txts_lock, flags);
|
||||||
|
idx = ether_get_free_tx_ts_node(pdata);
|
||||||
|
if (idx == ETHER_MAX_PENDING_SKB_CNT) {
|
||||||
|
dev_dbg(pdata->dev,
|
||||||
|
"No free node to store pending SKB\n");
|
||||||
|
dev_consume_skb_any(skb);
|
||||||
|
raw_spin_unlock_irqrestore(&pdata->txts_lock, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->tx_ts_skb[idx].in_use = OSI_ENABLE;
|
||||||
|
pnode = &pdata->tx_ts_skb[idx];
|
||||||
|
pnode->skb = skb;
|
||||||
|
pnode->pktid = pktid;
|
||||||
|
pnode->pkt_jiffies = now_jiffies;
|
||||||
|
|
||||||
|
dev_dbg(pdata->dev, "%s() SKB %p added for pktid = %x time=%lu\n",
|
||||||
|
__func__, skb, pktid, pnode->pkt_jiffies);
|
||||||
|
list_add_tail(&pnode->list_head,
|
||||||
|
&pdata->tx_ts_skb_head);
|
||||||
|
raw_spin_unlock_irqrestore(&pdata->txts_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds delay in micro seconds.
|
* @brief Adds delay in micro seconds.
|
||||||
*
|
*
|
||||||
@@ -650,29 +728,6 @@ done:
|
|||||||
ether_realloc_rx_skb(pdata, rx_ring, chan);
|
ether_realloc_rx_skb(pdata, rx_ring, chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ether_get_free_tx_ts_node - get free node for pending SKB
|
|
||||||
*
|
|
||||||
* Algorithm:
|
|
||||||
* - Find index of statically allocayted free memory for pending SKB
|
|
||||||
*
|
|
||||||
* @param[in] pdata: OSD private data structure.
|
|
||||||
*
|
|
||||||
* @retval index number
|
|
||||||
*/
|
|
||||||
static inline unsigned int ether_get_free_tx_ts_node(struct ether_priv_data *pdata)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ETHER_MAX_PENDING_SKB_CNT; i++) {
|
|
||||||
if (pdata->tx_ts_skb[i].in_use == OSI_NONE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief osd_transmit_complete - Transmit completion routine.
|
* @brief osd_transmit_complete - Transmit completion routine.
|
||||||
*
|
*
|
||||||
@@ -702,9 +757,7 @@ static void osd_transmit_complete(void *priv, const struct osi_tx_swcx *swcx,
|
|||||||
struct osi_tx_ring *tx_ring;
|
struct osi_tx_ring *tx_ring;
|
||||||
struct netdev_queue *txq;
|
struct netdev_queue *txq;
|
||||||
unsigned int chan, qinx;
|
unsigned int chan, qinx;
|
||||||
unsigned int idx;
|
|
||||||
unsigned int len = swcx->len;
|
unsigned int len = swcx->len;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
ndev->stats.tx_bytes += len;
|
ndev->stats.tx_bytes += len;
|
||||||
|
|
||||||
@@ -745,28 +798,7 @@ static void osd_transmit_complete(void *priv, const struct osi_tx_swcx *swcx,
|
|||||||
ndev->stats.tx_packets++;
|
ndev->stats.tx_packets++;
|
||||||
if ((txdone_pkt_cx->flags & OSI_TXDONE_CX_TS_DELAYED) ==
|
if ((txdone_pkt_cx->flags & OSI_TXDONE_CX_TS_DELAYED) ==
|
||||||
OSI_TXDONE_CX_TS_DELAYED) {
|
OSI_TXDONE_CX_TS_DELAYED) {
|
||||||
struct ether_tx_ts_skb_list *pnode = NULL;
|
add_skb_node(pdata, skb, txdone_pkt_cx->pktid);
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&pdata->txts_lock, flags);
|
|
||||||
idx = ether_get_free_tx_ts_node(pdata);
|
|
||||||
if (idx == ETHER_MAX_PENDING_SKB_CNT) {
|
|
||||||
dev_dbg(pdata->dev,
|
|
||||||
"No free node to store pending SKB\n");
|
|
||||||
dev_consume_skb_any(skb);
|
|
||||||
raw_spin_unlock_irqrestore(&pdata->txts_lock, flags);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdata->tx_ts_skb[idx].in_use = OSI_ENABLE;
|
|
||||||
pnode = &pdata->tx_ts_skb[idx];
|
|
||||||
pnode->skb = skb;
|
|
||||||
pnode->pktid = txdone_pkt_cx->pktid;
|
|
||||||
|
|
||||||
dev_dbg(pdata->dev, "SKB %p added for pktid = %d\n",
|
|
||||||
skb, txdone_pkt_cx->pktid);
|
|
||||||
list_add_tail(&pnode->list_head,
|
|
||||||
&pdata->tx_ts_skb_head);
|
|
||||||
raw_spin_unlock_irqrestore(&pdata->txts_lock, flags);
|
|
||||||
schedule_delayed_work(&pdata->tx_ts_work,
|
schedule_delayed_work(&pdata->tx_ts_work,
|
||||||
msecs_to_jiffies(ETHER_TS_MS_TIMER));
|
msecs_to_jiffies(ETHER_TS_MS_TIMER));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user