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:
Rakesh Goyal
2022-05-22 14:59:33 +05:30
committed by Revanth Kumar Uppala
parent d38959ba90
commit 118cdcebdc
2 changed files with 86 additions and 47 deletions

View File

@@ -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;
}; };
/** /**

View File

@@ -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 {