]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
octeontx2-pf: Free pending and dropped SQEs
authorGeetha sowjanya <gakula@marvell.com>
Tue, 31 Oct 2023 11:23:45 +0000 (16:53 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:57:23 +0000 (11:57 +0100)
[ Upstream commit 3423ca23e08bf285a324237abe88e7e7d9becfe6 ]

On interface down, the pending SQEs in the NIX get dropped
or drained out during SMQ flush. But skb's pointed by these
SQEs never get free or updated to the stack as respective CQE
never get added.
This patch fixes the issue by freeing all valid skb's in SQ SG list.

Fixes: b1bc8457e9d0 ("octeontx2-pf: Cleanup all receive buffers in SG descriptor")
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c

index 379e1510b70c0ca6f9d432a418816b956a649c2c..48bcd6f24fcde22bfaf415f6d32300650cfc5126 100644 (file)
@@ -816,7 +816,6 @@ void otx2_sqb_flush(struct otx2_nic *pfvf)
        int qidx, sqe_tail, sqe_head;
        struct otx2_snd_queue *sq;
        u64 incr, *ptr, val;
-       int timeout = 1000;
 
        ptr = (u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
        for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
@@ -825,15 +824,11 @@ void otx2_sqb_flush(struct otx2_nic *pfvf)
                        continue;
 
                incr = (u64)qidx << 32;
-               while (timeout) {
-                       val = otx2_atomic64_add(incr, ptr);
-                       sqe_head = (val >> 20) & 0x3F;
-                       sqe_tail = (val >> 28) & 0x3F;
-                       if (sqe_head == sqe_tail)
-                               break;
-                       usleep_range(1, 3);
-                       timeout--;
-               }
+               val = otx2_atomic64_add(incr, ptr);
+               sqe_head = (val >> 20) & 0x3F;
+               sqe_tail = (val >> 28) & 0x3F;
+               if (sqe_head != sqe_tail)
+                       usleep_range(50, 60);
        }
 }
 
index 0e81849db3538c7cbd51ce9c0ca9f0e118450af6..5590e30f8e2d0297e53d820c22c8ac5eb041cbb2 100644 (file)
@@ -972,6 +972,7 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
 int otx2_txsch_alloc(struct otx2_nic *pfvf);
 void otx2_txschq_stop(struct otx2_nic *pfvf);
 void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq);
+void otx2_free_pending_sqe(struct otx2_nic *pfvf);
 void otx2_sqb_flush(struct otx2_nic *pfvf);
 int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
                    dma_addr_t *dma);
index ca6602fe270504e5ae505a6303aef37e73ba083d..472d6982eabd255ef130ae49c1803fa9163da5f9 100644 (file)
@@ -1600,6 +1600,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
                else
                        otx2_cleanup_tx_cqes(pf, cq);
        }
+       otx2_free_pending_sqe(pf);
 
        otx2_free_sq_res(pf);
 
index 53b2a4ef52985271ab6d0ee67c779af878876ba0..6ee15f3c25ede947ce0103a7d8b00cd7291c177e 100644 (file)
@@ -1247,9 +1247,11 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int q
 
 void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
 {
+       int tx_pkts = 0, tx_bytes = 0;
        struct sk_buff *skb = NULL;
        struct otx2_snd_queue *sq;
        struct nix_cqe_tx_s *cqe;
+       struct netdev_queue *txq;
        int processed_cqe = 0;
        struct sg_list *sg;
        int qidx;
@@ -1270,12 +1272,20 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
                sg = &sq->sg[cqe->comp.sqe_id];
                skb = (struct sk_buff *)sg->skb;
                if (skb) {
+                       tx_bytes += skb->len;
+                       tx_pkts++;
                        otx2_dma_unmap_skb_frags(pfvf, sg);
                        dev_kfree_skb_any(skb);
                        sg->skb = (u64)NULL;
                }
        }
 
+       if (likely(tx_pkts)) {
+               if (qidx >= pfvf->hw.tx_queues)
+                       qidx -= pfvf->hw.xdp_queues;
+               txq = netdev_get_tx_queue(pfvf->netdev, qidx);
+               netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
+       }
        /* Free CQEs to HW */
        otx2_write64(pfvf, NIX_LF_CQ_OP_DOOR,
                     ((u64)cq->cq_idx << 32) | processed_cqe);
@@ -1302,6 +1312,38 @@ int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable)
        return err;
 }
 
+void otx2_free_pending_sqe(struct otx2_nic *pfvf)
+{
+       int tx_pkts = 0, tx_bytes = 0;
+       struct sk_buff *skb = NULL;
+       struct otx2_snd_queue *sq;
+       struct netdev_queue *txq;
+       struct sg_list *sg;
+       int sq_idx, sqe;
+
+       for (sq_idx = 0; sq_idx < pfvf->hw.tx_queues; sq_idx++) {
+               sq = &pfvf->qset.sq[sq_idx];
+               for (sqe = 0; sqe < sq->sqe_cnt; sqe++) {
+                       sg = &sq->sg[sqe];
+                       skb = (struct sk_buff *)sg->skb;
+                       if (skb) {
+                               tx_bytes += skb->len;
+                               tx_pkts++;
+                               otx2_dma_unmap_skb_frags(pfvf, sg);
+                               dev_kfree_skb_any(skb);
+                               sg->skb = (u64)NULL;
+                       }
+               }
+
+               if (!tx_pkts)
+                       continue;
+               txq = netdev_get_tx_queue(pfvf->netdev, sq_idx);
+               netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
+               tx_pkts = 0;
+               tx_bytes = 0;
+       }
+}
+
 static void otx2_xdp_sqe_add_sg(struct otx2_snd_queue *sq, u64 dma_addr,
                                int len, int *offset)
 {