[PATCH v2] common/cnxk: add NPA diagnostic and performance counter apis

Nawal Kishor nkishor at marvell.com
Mon Mar 16 07:27:17 CET 2026


Add DPC (Diagnostic and Performance Counter) support for NPA pool
operations on CN20K. This allows allocating and attaching hardware
counters to pool/aura for monitoring alloc/free, outstanding buffers,
and high-watermark.

Signed-off-by: Nawal Kishor <nkishor at marvell.com>
---
v2:
 * Fixed commit message.

 drivers/common/cnxk/hw/npa.h                  |  10 +
 drivers/common/cnxk/roc_features.h            |   6 +
 drivers/common/cnxk/roc_mbox.h                |  19 ++
 drivers/common/cnxk/roc_npa.c                 | 235 ++++++++++++++++++
 drivers/common/cnxk/roc_npa.h                 |  45 ++++
 drivers/common/cnxk/roc_npa_priv.h            |   2 +
 .../common/cnxk/roc_platform_base_symbols.c   |   4 +
 7 files changed, 321 insertions(+)

diff --git a/drivers/common/cnxk/hw/npa.h b/drivers/common/cnxk/hw/npa.h
index e421c70e01..8d6b6bbe8b 100644
--- a/drivers/common/cnxk/hw/npa.h
+++ b/drivers/common/cnxk/hw/npa.h
@@ -48,6 +48,8 @@
 #define NPA_AF_BATCH_ACCEPT_CTL	     (0x6a8ull) /* [CN10K, .) */
 #define NPA_AF_BATCH_ERR_DATA0	     (0x6c0ull) /* [CN10K, .) */
 #define NPA_AF_BATCH_ERR_DATA1	     (0x6c8ull) /* [CN10K, .) */
+#define NPA_AF_DPCX_CFG(a)           (0x800ull | (uint64_t)(a) << 6)  /* [CN20K, .) */
+#define NPA_AF_DPC_PERMITX(a)        (0x1000ull | (uint64_t)(a) << 3) /* [CN20K, .) */
 #define NPA_AF_LFX_AURAS_CFG(a)	     (0x4000ull | (uint64_t)(a) << 18)
 #define NPA_AF_LFX_LOC_AURAS_BASE(a) (0x4010ull | (uint64_t)(a) << 18)
 #define NPA_AF_LFX_QINTS_CFG(a)	     (0x4100ull | (uint64_t)(a) << 18)
@@ -89,6 +91,14 @@
 #define NPA_LF_AURA_BATCH_FREE0	  (0x400ull) /* [CN10K, .) */
 #define NPA_LF_AURA_BATCH_FREEX(a)                                             \
 	(0x400ull | (uint64_t)(a) << 3) /* [CN10K, .) */
+#define NPA_LF_DPCX_ALLOC_CNT(a)                                               \
+	(0x808ull | (uint64_t)(a) << 6) /* [CN20K, .) */
+#define NPA_LF_DPCX_FREE_CNT(a)                                                \
+	(0x810ull | (uint64_t)(a) << 6) /* [CN20K, .) */
+#define NPA_LF_DPCX_OUTST_BUF_CNT(a)                                           \
+	(0x818ull | (uint64_t)(a) << 6) /* [CN20K, .) */
+#define NPA_LF_DPCX_CNT_HI_WM(a)                                               \
+	(0x820ull | (uint64_t)(a) << 6) /* [CN20K, .) */
 
 /* Enum offsets */
 
diff --git a/drivers/common/cnxk/roc_features.h b/drivers/common/cnxk/roc_features.h
index 3c34041d76..2d8bad5b0c 100644
--- a/drivers/common/cnxk/roc_features.h
+++ b/drivers/common/cnxk/roc_features.h
@@ -132,6 +132,12 @@ roc_feature_nix_has_sq_cnt_update(void)
 	return roc_model_is_cn20k();
 }
 
+static inline bool
+roc_feature_npa_has_dpc(void)
+{
+	return roc_model_is_cn20k();
+}
+
 static inline bool
 roc_feature_nix_has_16b_align(void)
 {
diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index 3176c87382..e86446c339 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -123,6 +123,10 @@ struct mbox_msghdr {
 	  msg_rsp)                                                             \
 	M(NPA_CN20K_AQ_ENQ, 0x404, npa_cn20k_aq_enq, npa_cn20k_aq_enq_req,     \
 	  npa_cn20k_aq_enq_rsp)                                                \
+	M(NPA_CN20K_DPC_ALLOC, 0x405, npa_cn20k_dpc_alloc,                     \
+	  npa_cn20k_dpc_alloc_req, npa_cn20k_dpc_alloc_rsp)                    \
+	M(NPA_CN20K_DPC_FREE,  0x406, npa_cn20k_dpc_free,                      \
+	  npa_cn20k_dpc_free_req, msg_rsp)                                     \
 	/* SSO/SSOW mbox IDs (range 0x600 - 0x7FF) */                          \
 	M(SSO_LF_ALLOC, 0x600, sso_lf_alloc, sso_lf_alloc_req,                 \
 	  sso_lf_alloc_rsp)                                                    \
@@ -1423,6 +1427,21 @@ struct npa_cn20k_aq_enq_rsp {
 	};
 };
 
+struct npa_cn20k_dpc_alloc_req {
+	struct mbox_msghdr hdr;
+	uint16_t __io dpc_conf;
+};
+
+struct npa_cn20k_dpc_alloc_rsp {
+	struct mbox_msghdr hdr;
+	uint8_t __io cntr_id;
+};
+
+struct npa_cn20k_dpc_free_req {
+	struct mbox_msghdr hdr;
+	uint8_t __io cntr_id;
+};
+
 /* Disable all contexts of type 'ctype' */
 struct hwctx_disable_req {
 	struct mbox_msghdr hdr;
diff --git a/drivers/common/cnxk/roc_npa.c b/drivers/common/cnxk/roc_npa.c
index 10087e19ef..88e328105a 100644
--- a/drivers/common/cnxk/roc_npa.c
+++ b/drivers/common/cnxk/roc_npa.c
@@ -1803,3 +1803,238 @@ roc_npa_dev_unlock(void)
 	if (idev != NULL)
 		plt_spinlock_unlock(&idev->npa_dev_lock);
 }
+
+int
+roc_npa_dpc_alloc(uint8_t *counter_id, uint16_t conf)
+{
+	struct npa_cn20k_dpc_alloc_req *req;
+	struct npa_cn20k_dpc_alloc_rsp *rsp;
+	int rc = NPA_ERR_DPC_ALLOC, off;
+	struct mbox_dev *mdev;
+	struct mbox *mbox;
+	struct npa_lf *lf;
+
+	lf = idev_npa_obj_get();
+	if (lf == NULL) {
+		rc = NPA_ERR_DEVICE_NOT_BOUNDED;
+		return rc;
+	}
+	mdev = &lf->mbox->dev[0];
+
+	mbox = mbox_get(lf->mbox);
+	req = mbox_alloc_msg_npa_cn20k_dpc_alloc(mbox);
+	if (req == NULL)
+		goto exit;
+
+	req->dpc_conf = conf;
+	rc = mbox_process(mbox);
+	if (rc < 0)
+		goto exit;
+
+	off = mbox->rx_start +
+	      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+	rsp = (struct npa_cn20k_dpc_alloc_rsp *)((uintptr_t)mdev->mbase + off);
+
+	if (rsp->hdr.rc != 0)
+		goto exit;
+
+	*counter_id = rsp->cntr_id;
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
+int
+roc_npa_dpc_free(uint8_t counter_id)
+{
+	struct npa_cn20k_dpc_free_req *free_req;
+	int rc = NPA_ERR_DPC_FREE, off;
+	struct mbox_dev *mdev;
+	struct msg_rsp *rsp;
+	struct mbox *mbox;
+	struct npa_lf *lf;
+
+	lf = idev_npa_obj_get();
+	if (lf == NULL) {
+		rc = NPA_ERR_DEVICE_NOT_BOUNDED;
+		return rc;
+	}
+	mdev = &lf->mbox->dev[0];
+	mbox = mbox_get(lf->mbox);
+	free_req = mbox_alloc_msg_npa_cn20k_dpc_free(mbox);
+	if (free_req == NULL)
+		goto exit;
+
+	free_req->cntr_id = counter_id;
+	rc = mbox_process(mbox);
+	if (rc < 0)
+		goto exit;
+
+	off = mbox->rx_start +
+	      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+	rsp = (struct msg_rsp *)((uintptr_t)mdev->mbase + off);
+	if (rsp->hdr.rc != 0)
+		goto exit;
+
+	rc = 0;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
+int
+roc_npa_pool_dpc_enable(uint64_t aura_handle, uint8_t counter_id, uint32_t flags)
+{
+	struct npa_cn20k_aq_enq_req *req;
+	struct npa_cn20k_aq_enq_rsp *rsp;
+	int rc = -ENOSPC, off;
+	struct mbox_dev *mdev;
+	struct mbox *mbox;
+	struct npa_lf *lf;
+
+	lf = idev_npa_obj_get();
+	if (lf == NULL) {
+		rc = NPA_ERR_DEVICE_NOT_BOUNDED;
+		return rc;
+	}
+	mdev = &lf->mbox->dev[0];
+	mbox = mbox_get(lf->mbox);
+	req = mbox_alloc_msg_npa_cn20k_aq_enq(mbox);
+	if (req == NULL)
+		goto exit;
+
+	req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
+	req->op = NPA_AQ_INSTOP_WRITE;
+	if (!(flags & ROC_NPA_HALO_F)) {
+		/* Enable DPC in Pool */
+		req->ctype = NPA_AQ_CTYPE_POOL;
+		req->pool.op_dpc_ena = 1;
+		req->pool.op_dpc_set = counter_id;
+		req->pool_mask.op_dpc_ena = 1;
+		req->pool_mask.op_dpc_set = 0;
+		req->pool_mask.op_dpc_set = ~req->pool_mask.op_dpc_set;
+	} else {
+		/* Enable DPC in Halo */
+		req->ctype = NPA_AQ_CTYPE_HALO;
+		req->halo.op_dpc_ena = 1;
+		req->halo.op_dpc_set = counter_id;
+		req->halo_mask.op_dpc_ena = 1;
+		req->halo_mask.op_dpc_set = 0;
+		req->halo_mask.op_dpc_set = ~req->halo_mask.op_dpc_set;
+	}
+
+	rc = mbox_process(mbox);
+	if (rc < 0)
+		goto exit;
+
+	off = mbox->rx_start +
+	      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+	rsp = (struct npa_cn20k_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
+	if (rsp->hdr.rc != 0)
+		goto exit;
+
+	if (!(flags & ROC_NPA_HALO_F)) {
+		req = mbox_alloc_msg_npa_cn20k_aq_enq(mbox);
+		if (req == NULL)
+			goto disable;
+
+		/* Enable DPC in Aura */
+		req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
+		req->op = NPA_AQ_INSTOP_WRITE;
+		req->ctype = NPA_AQ_CTYPE_AURA;
+		req->aura.op_dpc_ena = 1;
+		req->aura.op_dpc_set = counter_id;
+		req->aura_mask.op_dpc_ena = 1;
+		req->aura_mask.op_dpc_set = 0;
+		req->aura_mask.op_dpc_set = ~req->aura_mask.op_dpc_set;
+
+		rc = mbox_process(mbox);
+		if (rc < 0)
+			goto disable;
+
+		off = mbox->rx_start +
+		      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+		rsp = (struct npa_cn20k_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
+		if (rsp->hdr.rc != 0)
+			goto disable;
+	}
+	rc = 0;
+	goto exit;
+
+disable:
+	roc_npa_pool_dpc_disable(aura_handle, flags);
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
+int
+roc_npa_pool_dpc_disable(uint64_t aura_handle, uint32_t flags)
+{
+	struct npa_cn20k_aq_enq_req *req;
+	struct npa_cn20k_aq_enq_rsp *rsp;
+	int rc = -ENOSPC, off;
+	struct mbox_dev *mdev;
+	struct mbox *mbox;
+	struct npa_lf *lf;
+
+	lf = idev_npa_obj_get();
+	if (lf == NULL) {
+		rc = NPA_ERR_DEVICE_NOT_BOUNDED;
+		return rc;
+	}
+	mdev = &lf->mbox->dev[0];
+	mbox = mbox_get(lf->mbox);
+	req = mbox_alloc_msg_npa_cn20k_aq_enq(mbox);
+	if (req == NULL)
+		goto exit;
+
+	req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
+	req->op = NPA_AQ_INSTOP_WRITE;
+	if (!(flags & ROC_NPA_HALO_F)) {
+		req->ctype = NPA_AQ_CTYPE_POOL;
+		req->pool.op_dpc_ena = 0;
+		req->pool_mask.op_dpc_ena = 1;
+	} else {
+		req->ctype = NPA_AQ_CTYPE_HALO;
+		req->halo.op_dpc_ena = 0;
+		req->halo_mask.op_dpc_ena = 1;
+	}
+
+	rc = mbox_process(mbox);
+	if (rc < 0)
+		goto exit;
+
+	off = mbox->rx_start +
+	      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+	rsp = (struct npa_cn20k_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
+	if (rsp->hdr.rc != 0)
+		goto exit;
+
+	if (!(flags & ROC_NPA_HALO_F)) {
+		req = mbox_alloc_msg_npa_cn20k_aq_enq(mbox);
+		if (req == NULL)
+			goto exit;
+
+		req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
+		req->op = NPA_AQ_INSTOP_WRITE;
+		req->ctype = NPA_AQ_CTYPE_AURA;
+		req->aura.op_dpc_ena = 0;
+		req->aura_mask.op_dpc_ena = 1;
+		rc = mbox_process(mbox);
+		if (rc < 0)
+			goto exit;
+
+		off = mbox->rx_start + PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+		rsp = (struct npa_cn20k_aq_enq_rsp *)((uintptr_t)mdev->mbase + off);
+		if (rsp->hdr.rc != 0)
+			goto exit;
+	}
+
+	rc = 0;
+
+exit:
+	mbox_put(mbox);
+	return rc;
+}
diff --git a/drivers/common/cnxk/roc_npa.h b/drivers/common/cnxk/roc_npa.h
index 18808e5873..db610cbd2c 100644
--- a/drivers/common/cnxk/roc_npa.h
+++ b/drivers/common/cnxk/roc_npa.h
@@ -191,6 +191,47 @@ roc_npa_aura_op_available_wait(uint64_t aura_handle, uint32_t count,
 	return op_avail;
 }
 
+static inline void
+roc_npa_pool_op_dpc_reset(uint64_t aura_handle, uint8_t counter_id)
+{
+	plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
+		       NPA_LF_DPCX_ALLOC_CNT(counter_id));
+	plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
+		       NPA_LF_DPCX_FREE_CNT(counter_id));
+	plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
+		       NPA_LF_DPCX_OUTST_BUF_CNT(counter_id));
+	plt_write64(0, roc_npa_aura_handle_to_base(aura_handle) +
+		       NPA_LF_DPCX_CNT_HI_WM(counter_id));
+}
+
+static inline uint64_t
+roc_npa_pool_op_dpc_alloc_count(uint64_t aura_handle, uint8_t counter_id)
+{
+	return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
+			  NPA_LF_DPCX_ALLOC_CNT(counter_id));
+}
+
+static inline uint64_t
+roc_npa_pool_op_dpc_free_count(uint64_t aura_handle, uint8_t counter_id)
+{
+	return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
+			  NPA_LF_DPCX_FREE_CNT(counter_id));
+}
+
+static inline uint64_t
+roc_npa_pool_op_dpc_outst_buf_count(uint64_t aura_handle, uint8_t counter_id)
+{
+	return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
+			  NPA_LF_DPCX_OUTST_BUF_CNT(counter_id));
+}
+
+static inline uint64_t
+roc_npa_pool_op_dpc_high_wm_count(uint64_t aura_handle, uint8_t counter_id)
+{
+	return plt_read64(roc_npa_aura_handle_to_base(aura_handle) +
+			  NPA_LF_DPCX_CNT_HI_WM(counter_id));
+}
+
 static inline uint64_t
 roc_npa_pool_op_performance_counter(uint64_t aura_handle, const int drop)
 {
@@ -852,5 +893,9 @@ int __roc_api roc_npa_aura_drop_set(uint64_t aura_handle, uint64_t limit,
 
 void __roc_api roc_npa_dev_lock(void);
 void __roc_api roc_npa_dev_unlock(void);
+int __roc_api roc_npa_dpc_alloc(uint8_t *counter_id, uint16_t conf);
+int __roc_api roc_npa_dpc_free(uint8_t counter_id);
+int __roc_api roc_npa_pool_dpc_enable(uint64_t aura_handle, uint8_t counter_id, uint32_t flags);
+int __roc_api roc_npa_pool_dpc_disable(uint64_t aura_handle, uint32_t flags);
 
 #endif /* _ROC_NPA_H_ */
diff --git a/drivers/common/cnxk/roc_npa_priv.h b/drivers/common/cnxk/roc_npa_priv.h
index e437fe831a..a3bda39f73 100644
--- a/drivers/common/cnxk/roc_npa_priv.h
+++ b/drivers/common/cnxk/roc_npa_priv.h
@@ -16,6 +16,8 @@ enum npa_error_status {
 	NPA_ERR_DEVICE_NOT_BOUNDED = -519,
 	NPA_ERR_HALO_INIT = -520,
 	NPA_ERR_HALO_FINI = -521,
+	NPA_ERR_DPC_ALLOC = -522,
+	NPA_ERR_DPC_FREE = -523,
 };
 
 struct npa_lf {
diff --git a/drivers/common/cnxk/roc_platform_base_symbols.c b/drivers/common/cnxk/roc_platform_base_symbols.c
index 79dd18fbd7..65db0c77bd 100644
--- a/drivers/common/cnxk/roc_platform_base_symbols.c
+++ b/drivers/common/cnxk/roc_platform_base_symbols.c
@@ -452,6 +452,10 @@ RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_dump)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_buf_type_update)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_buf_type_mask)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_buf_type_limit_get)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_dpc_alloc)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_dpc_free)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_pool_dpc_enable)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_npa_pool_dpc_disable)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_mark_actions_get)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_mark_actions_sub_return)
 RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_vtag_actions_get)
-- 
2.48.1



More information about the dev mailing list