]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
octeontx2-pf: Fix SQE threshold checking
authorRatheesh Kannoth <rkannoth@marvell.com>
Mon, 7 Nov 2022 03:35:05 +0000 (09:05 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Nov 2022 09:03:58 +0000 (10:03 +0100)
[ Upstream commit f0dfc4c88ef39be0ba736aa0ce6119263fc19aeb ]

Current way of checking available SQE count which is based on
HW updated SQB count could result in driver submitting an SQE
even before CQE for the previously transmitted SQE at the same
index is processed in NAPI resulting losing SKB pointers,
hence a leak. Fix this by checking a consumer index which
is updated once CQE is processed.

Fixes: 3ca6c4c882a7 ("octeontx2-pf: Add packet transmission support")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Reviewed-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Link: https://lore.kernel.org/r/20221107033505.2491464-1-rkannoth@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h

index d686c7b6252f41946282dd99bf85905064e92e43..9c2baa437c2314f67d658d08658b622c064fed2e 100644 (file)
@@ -863,6 +863,7 @@ static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
        }
 
        sq->head = 0;
+       sq->cons_head = 0;
        sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1;
        sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb;
        /* Set SQE threshold to 10% of total SQEs */
index a18e8efd0f1ee53d891e9fd8faaef39aa2df1774..664f977433f4a9b9d074a45dae2648e90bf81251 100644 (file)
@@ -435,6 +435,7 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
                                struct otx2_cq_queue *cq, int budget)
 {
        int tx_pkts = 0, tx_bytes = 0, qidx;
+       struct otx2_snd_queue *sq;
        struct nix_cqe_tx_s *cqe;
        int processed_cqe = 0;
 
@@ -445,6 +446,9 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
                return 0;
 
 process_cqe:
+       qidx = cq->cq_idx - pfvf->hw.rx_queues;
+       sq = &pfvf->qset.sq[qidx];
+
        while (likely(processed_cqe < budget) && cq->pend_cqe) {
                cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq);
                if (unlikely(!cqe)) {
@@ -452,18 +456,20 @@ process_cqe:
                                return 0;
                        break;
                }
+
                if (cq->cq_type == CQ_XDP) {
-                       qidx = cq->cq_idx - pfvf->hw.rx_queues;
-                       otx2_xdp_snd_pkt_handler(pfvf, &pfvf->qset.sq[qidx],
-                                                cqe);
+                       otx2_xdp_snd_pkt_handler(pfvf, sq, cqe);
                } else {
-                       otx2_snd_pkt_handler(pfvf, cq,
-                                            &pfvf->qset.sq[cq->cint_idx],
-                                            cqe, budget, &tx_pkts, &tx_bytes);
+                       otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget,
+                                            &tx_pkts, &tx_bytes);
                }
+
                cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID;
                processed_cqe++;
                cq->pend_cqe--;
+
+               sq->cons_head++;
+               sq->cons_head &= (sq->sqe_cnt - 1);
        }
 
        /* Free CQEs to HW */
@@ -972,17 +978,17 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
 {
        struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx);
        struct otx2_nic *pfvf = netdev_priv(netdev);
-       int offset, num_segs, free_sqe;
+       int offset, num_segs, free_desc;
        struct nix_sqe_hdr_s *sqe_hdr;
 
-       /* Check if there is room for new SQE.
-        * 'Num of SQBs freed to SQ's pool - SQ's Aura count'
-        * will give free SQE count.
+       /* Check if there is enough room between producer
+        * and consumer index.
         */
-       free_sqe = (sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb;
+       free_desc = (sq->cons_head - sq->head - 1 + sq->sqe_cnt) & (sq->sqe_cnt - 1);
+       if (free_desc < sq->sqe_thresh)
+               return false;
 
-       if (free_sqe < sq->sqe_thresh ||
-           free_sqe < otx2_get_sqe_count(pfvf, skb))
+       if (free_desc < otx2_get_sqe_count(pfvf, skb))
                return false;
 
        num_segs = skb_shinfo(skb)->nr_frags + 1;
index fbe62bbfb789afbf875c177ef4835bb42f9efabc..93cac2c2664c204d72f428c2661f89ab61a124c4 100644 (file)
@@ -79,6 +79,7 @@ struct sg_list {
 struct otx2_snd_queue {
        u8                      aura_id;
        u16                     head;
+       u16                     cons_head;
        u16                     sqe_size;
        u32                     sqe_cnt;
        u16                     num_sqbs;