From 118cdcebdc6624f4c5f14bc2bc8351c86ddcb083 Mon Sep 17 00:00:00 2001 From: Rakesh Goyal Date: Sun, 22 May 2022 14:59:33 +0530 Subject: [PATCH] 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 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2716400 Reviewed-by: Bharat Nihalani Reviewed-by: svc_kernel_abi GVS: Gerrit_Virtual_Submit --- .../ethernet/nvidia/nvethernet/ether_linux.h | 7 + drivers/net/ethernet/nvidia/nvethernet/osd.c | 126 +++++++++++------- 2 files changed, 86 insertions(+), 47 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h index efc79be8..8c9a6a24 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h @@ -130,6 +130,11 @@ */ #define TS_MISS_THRESHOLD 200U +/** + * @brief SEC to MSEC converter + */ +#define ETHER_SECTOMSEC 1000U + /** * @brief Ethernet clk rates */ @@ -388,6 +393,8 @@ struct ether_tx_ts_skb_list { struct sk_buff *skb; /** packet id to identify timestamp */ unsigned int pktid; + /** SKB jiffies to find time */ + unsigned long pkt_jiffies; }; /** diff --git a/drivers/net/ethernet/nvidia/nvethernet/osd.c b/drivers/net/ethernet/nvidia/nvethernet/osd.c index f5d6b86e..0f22d0b5 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/osd.c +++ b/drivers/net/ethernet/nvidia/nvethernet/osd.c @@ -16,6 +16,84 @@ #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. * @@ -650,29 +728,6 @@ done: 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. * @@ -702,9 +757,7 @@ static void osd_transmit_complete(void *priv, const struct osi_tx_swcx *swcx, struct osi_tx_ring *tx_ring; struct netdev_queue *txq; unsigned int chan, qinx; - unsigned int idx; unsigned int len = swcx->len; - unsigned long flags; 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++; if ((txdone_pkt_cx->flags & OSI_TXDONE_CX_TS_DELAYED) == OSI_TXDONE_CX_TS_DELAYED) { - struct ether_tx_ts_skb_list *pnode = NULL; - - 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); + add_skb_node(pdata, skb, txdone_pkt_cx->pktid); schedule_delayed_work(&pdata->tx_ts_work, msecs_to_jiffies(ETHER_TS_MS_TIMER)); } else {