[PATCH 25.11] common/cnxk: fix CPT CQ roll over handling

Rahul Bhansali rbhansali at marvell.com
Tue Mar 3 07:39:34 CET 2026


[ upstream commit 63b16e2671061e4f7d09988ae3f8cd67a6dec0d9 ]

This fixes the handling of CPT CQ ring roll over case.

Fixes: a7d64a7740e0 ("net/cnxk: handle soft expiry")
Cc: stable at dpdk.org

Signed-off-by: Rahul Bhansali <rbhansali at marvell.com>
---
 drivers/common/cnxk/roc_cpt.c             |  2 +-
 drivers/common/cnxk/roc_cpt.h             |  1 +
 drivers/common/cnxk/roc_nix_inl.c         | 43 ++++++++++++++++++-----
 drivers/common/cnxk/roc_nix_inl_dev_irq.c | 18 ++++++----
 4 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/drivers/common/cnxk/roc_cpt.c b/drivers/common/cnxk/roc_cpt.c
index edd73536e0..13eb9d3767 100644
--- a/drivers/common/cnxk/roc_cpt.c
+++ b/drivers/common/cnxk/roc_cpt.c
@@ -711,7 +711,7 @@ cpt_lf_cq_init(struct roc_cpt_lf *lf)
 
 	lf_cq_base.s.addr = addr >> 7;
 	plt_write64(lf_cq_base.u, lf->rbase + CPT_LF_CQ_BASE);
-	lf_cq_size.s.size = PLT_ALIGN(len, ROC_ALIGN);
+	lf_cq_size.s.size = lf->cq_size;
 	plt_write64(lf_cq_size.u, lf->rbase + CPT_LF_CQ_SIZE);
 
 	return 0;
diff --git a/drivers/common/cnxk/roc_cpt.h b/drivers/common/cnxk/roc_cpt.h
index 67956758be..7547d0b020 100644
--- a/drivers/common/cnxk/roc_cpt.h
+++ b/drivers/common/cnxk/roc_cpt.h
@@ -159,6 +159,7 @@ struct roc_cpt_lf {
 	bool cpt_cq_ena;
 	uint8_t cq_entry_size;
 	uint32_t cq_size;
+	uint32_t cq_head;
 	/* End of Input parameters */
 	struct plt_pci_device *pci_dev;
 	struct dev *dev;
diff --git a/drivers/common/cnxk/roc_nix_inl.c b/drivers/common/cnxk/roc_nix_inl.c
index 4ff2722dbe..8aa18dea8c 100644
--- a/drivers/common/cnxk/roc_nix_inl.c
+++ b/drivers/common/cnxk/roc_nix_inl.c
@@ -1585,8 +1585,19 @@ roc_nix_inl_outb_init(struct roc_nix *roc_nix)
 		lf->msixoff = nix->cpt_msixoff[i];
 		lf->pci_dev = nix->pci_dev;
 
+		if (roc_feature_nix_has_cpt_cq_support()) {
+			if (inl_dev && inl_dev->cpt_cq_ena) {
+				lf->dq_ack_ena = true;
+				lf->cpt_cq_ena = true;
+				lf->cq_entry_size = 0;
+				lf->cq_all = 0;
+				lf->cq_size = lf->nb_desc;
+				lf->cq_head = 1;
+			}
+		}
+
 		/* Setup CPT LF instruction queue */
-		rc = cpt_lf_init(lf, false);
+		rc = cpt_lf_init(lf, lf->cpt_cq_ena);
 		if (rc) {
 			plt_err("Failed to initialize CPT LF, rc=%d", rc);
 			goto lf_fini;
@@ -1603,6 +1614,13 @@ roc_nix_inl_outb_init(struct roc_nix *roc_nix)
 
 		/* Enable IQ */
 		roc_cpt_iq_enable(lf);
+		/* Enable CQ */
+		if (lf->cpt_cq_ena) {
+			rc = cpt_lf_register_irqs(lf, cpt_lf_misc_irq, nix_inl_cpt_done_irq);
+			if (rc)
+				goto lf_fini;
+			roc_cpt_cq_enable(lf);
+		}
 	}
 
 	if (!roc_nix->ipsec_out_max_sa)
@@ -1641,6 +1659,9 @@ roc_nix_inl_outb_init(struct roc_nix *roc_nix)
 	nix->outb_se_ring_base =
 		roc_nix->port_id * ROC_NIX_SOFT_EXP_PER_PORT_MAX_RINGS;
 
+	/* Fetch engine capabilities */
+	nix_inl_eng_caps_get(nix);
+
 	if (inl_dev == NULL || !inl_dev->set_soft_exp_poll) {
 		nix->outb_se_ring_cnt = 0;
 		return 0;
@@ -1664,13 +1685,15 @@ roc_nix_inl_outb_init(struct roc_nix *roc_nix)
 		}
 	}
 
-	/* Fetch engine capabilities */
-	nix_inl_eng_caps_get(nix);
 	return 0;
 
 lf_fini:
-	for (j = i - 1; j >= 0; j--)
-		cpt_lf_fini(&lf_base[j], false);
+	for (j = i - 1; j >= 0; j--) {
+		lf = &lf_base[j];
+		cpt_lf_fini(lf, lf->cpt_cq_ena);
+		if (lf->cpt_cq_ena)
+			cpt_lf_unregister_irqs(lf, cpt_lf_misc_irq, nix_inl_cpt_done_irq);
+	}
 	plt_free(lf_base);
 lf_free:
 	rc |= cpt_lfs_free(dev);
@@ -1687,6 +1710,7 @@ roc_nix_inl_outb_fini(struct roc_nix *roc_nix)
 	struct idev_cfg *idev = idev_get_cfg();
 	struct dev *dev = &nix->dev;
 	struct nix_inl_dev *inl_dev;
+	struct roc_cpt_lf *lf;
 	uint64_t *ring_base;
 	int i, rc, ret = 0;
 
@@ -1696,9 +1720,12 @@ roc_nix_inl_outb_fini(struct roc_nix *roc_nix)
 	nix->inl_outb_ena = false;
 
 	/* Cleanup CPT LF instruction queue */
-	for (i = 0; i < nix->nb_cpt_lf; i++)
-		cpt_lf_fini(&lf_base[i], false);
-
+	for (i = 0; i < nix->nb_cpt_lf; i++) {
+		lf = &lf_base[i];
+		cpt_lf_fini(lf, lf->cpt_cq_ena);
+		if (lf->cpt_cq_ena)
+			cpt_lf_unregister_irqs(lf, cpt_lf_misc_irq, nix_inl_cpt_done_irq);
+	}
 	/* Free LF resources */
 	rc = cpt_lfs_free(dev);
 	if (rc)
diff --git a/drivers/common/cnxk/roc_nix_inl_dev_irq.c b/drivers/common/cnxk/roc_nix_inl_dev_irq.c
index 1c4822925c..89155a1f7d 100644
--- a/drivers/common/cnxk/roc_nix_inl_dev_irq.c
+++ b/drivers/common/cnxk/roc_nix_inl_dev_irq.c
@@ -57,8 +57,8 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 	union cpt_lf_cq_ptr cq_ptr;
 	struct cpt_cq_s *cq_s;
 	uint8_t fmt_msk = 0x3;
-	uint64_t nq_ptr;
-	uint32_t count;
+	uint32_t count, head;
+	uint32_t nq_ptr;
 	uint64_t i;
 
 	if (idev)
@@ -69,14 +69,15 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 		return;
 	}
 
+	head = lf->cq_head;
 	cq_base.u = plt_read64(lf->rbase + CPT_LF_CQ_BASE);
 	cq_ptr.u = plt_read64(lf->rbase + CPT_LF_CQ_PTR);
 	count = cq_ptr.s.count;
-
-	nq_ptr = (((cq_base.s.addr << 7)) + ((cq_ptr.s.nq_ptr - count) << 5));
-	cq_s = (struct cpt_cq_s *)nq_ptr;
+	nq_ptr = cq_ptr.s.nq_ptr;
 
 	for (i = 0; i < count; i++) {
+		cq_s = (struct cpt_cq_s *)(uintptr_t)(((cq_base.s.addr << 7)) + (head << 5));
+
 		if (cq_s->w0.s.uc_compcode && cq_s->w0.s.compcode) {
 			switch (cq_s->w2.s.fmt & fmt_msk) {
 			case WQE_PTR_CPTR:
@@ -93,8 +94,13 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 			inl_dev->work_cb(&tmp, sa, NIX_INL_CPT_CQ, (void *)cq_s, port_id);
 		}
 done:
-		cq_s = cq_s + 1;
+		head = (head + 1) % lf->cq_size;
 	}
+
+	lf->cq_head = head;
+	if (unlikely(nq_ptr != head))
+		plt_err("CPT LF[%d] CQ head %d != NQ ptr %d", lf->lf_id, head, nq_ptr);
+
 	/* Acknowledge the number of completed requests */
 	plt_write64(count, lf->rbase + CPT_LF_DONE_ACK);
 }
-- 
2.34.1



More information about the stable mailing list