[PATCH 3/5] common/cnxk: fix null callback deref in CPT IRQ

Aarnav JP ajp at marvell.com
Mon Nov 2 13:21:51 CET 2026


nix_inl_cpt_cq_cb() dispatched through inl_dev->work_cb() without a NULL
check, unlike the SSO sibling path. A CPT completion processed before the
callback is registered or after it is cleared caused a NULL
function-pointer call on the interrupt thread, crashing the PMD.

Snapshot the callback once and skip dispatch when it is NULL; the entries
are still drained and the interrupt acknowledged, so the queue does not
stall.

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

Signed-off-by: Aarnav JP <ajp at marvell.com>
---
 drivers/common/cnxk/roc_nix_inl_dev_irq.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/common/cnxk/roc_nix_inl_dev_irq.c b/drivers/common/cnxk/roc_nix_inl_dev_irq.c
index 977b5e05e2..82f8c5edfb 100644
--- a/drivers/common/cnxk/roc_nix_inl_dev_irq.c
+++ b/drivers/common/cnxk/roc_nix_inl_dev_irq.c
@@ -50,6 +50,7 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 {
 	struct idev_cfg *idev = idev_get_cfg();
 	struct nix_inl_dev *inl_dev = NULL;
+	roc_nix_inl_sso_work_cb_t work_cb;
 	enum nix_inl_event_type cq_type;
 	uint32_t port_id = UINT32_MAX;
 	union cpt_lf_cq_base cq_base;
@@ -102,6 +103,9 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 		port_id = roc_nix->port_id;
 	}
 
+	/* Snapshot once so the test and the call use the same pointer */
+	work_cb = inl_dev->work_cb;
+
 	for (i = 0; i < count; i++) {
 		cq_s = (struct cpt_cq_s *)(uintptr_t)((((uint64_t)cq_base.s.addr << 7)) +
 						      (head << 5));
@@ -129,7 +133,8 @@ nix_inl_cpt_cq_cb(struct roc_cpt_lf *lf)
 				goto done;
 			}
 			gw[1] = (uint64_t)(uintptr_t)wqe;
-			inl_dev->work_cb(gw, sa, cq_type, (void *)cq_s, port_id);
+			if (work_cb)
+				work_cb(gw, sa, cq_type, (void *)cq_s, port_id);
 		}
 done:
 		head = (head + 1) % lf->cq_size;
-- 
2.43.0



More information about the stable mailing list