* [PATCH v4 02/19] bus/dpaa: scan max BPID from DTS
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Calculate the maximum BPID dynamically from the device tree
configuration instead of using a hardcoded value. This ensures
correct operation across different DPAA hardware configurations.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman_driver.c | 48 ++++++++++++++++-------
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman_driver.c b/drivers/bus/dpaa/base/qbman/bman_driver.c
index 23e44ac10b..85575192bf 100644
--- a/drivers/bus/dpaa/base/qbman/bman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/bman_driver.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017 NXP
+ * Copyright 2017,2026 NXP
*
*/
@@ -182,7 +182,12 @@ int bman_init_ccsr(const struct device_node *node)
int bman_global_init(void)
{
const struct device_node *dt_node;
+ const rte_be32_t *range;
+ uint32_t start, count;
+ int ret;
static int done;
+#define BPID_RANGE_START_INDEX 0
+#define BPID_RANGE_COUNT_INDEX 1
if (done)
return -EBUSY;
@@ -197,36 +202,49 @@ int bman_global_init(void)
if (of_device_is_compatible(dt_node, "fsl,bman-portal-1.0") ||
of_device_is_compatible(dt_node, "fsl,bman-portal-1.0.0")) {
bman_ip_rev = BMAN_REV10;
- bman_pool_max = 64;
} else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.0") ||
of_device_is_compatible(dt_node, "fsl,bman-portal-2.0.8")) {
bman_ip_rev = BMAN_REV20;
- bman_pool_max = 8;
} else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.0") ||
of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.1") ||
of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.2") ||
of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.3")) {
bman_ip_rev = BMAN_REV21;
- bman_pool_max = 64;
} else {
- pr_warn("unknown BMan version in portal node,default "
- "to rev1.0");
+ pr_warn("unknown BMan version in portal node, default to rev1.0");
bman_ip_rev = BMAN_REV10;
- bman_pool_max = 64;
}
if (!bman_ip_rev) {
pr_err("Unknown bman portal version\n");
return -ENODEV;
}
- {
- const struct device_node *dn = of_find_compatible_node(NULL,
- NULL, "fsl,bman");
- if (!dn)
- pr_err("No bman device node available");
-
- if (bman_init_ccsr(dn))
- pr_err("BMan CCSR map failed.");
+
+ for_each_compatible_node(dt_node, NULL, "fsl,bpid-range") {
+ range = of_get_property(dt_node, "fsl,bpid-range", NULL);
+ if (!range)
+ continue;
+ start = rte_be_to_cpu_32(range[BPID_RANGE_START_INDEX]);
+ count = rte_be_to_cpu_32(range[BPID_RANGE_COUNT_INDEX]);
+ bman_pool_max = start + count;
+ pr_info("Max BPID: %d, fixed BPID < %d", bman_pool_max, start);
+ break;
+ }
+ if (!bman_pool_max) {
+ pr_err("No BPID range found");
+ return -ENODEV;
+ }
+
+ dt_node = of_find_compatible_node(NULL, NULL, "fsl,bman");
+ if (!dt_node) {
+ pr_err("No bman device node available");
+ return -ENODEV;
+ }
+
+ ret = bman_init_ccsr(dt_node);
+ if (ret) {
+ pr_err("Failed(%d) to init bman ccsr", ret);
+ return ret;
}
done = 1;
--
2.25.1
^ permalink raw reply related
* [PATCH v4 03/19] drivers: add BMI Tx statistics
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Add support for BMI (Buffer Manager Interface) Tx statistics
counters. Extend fman_hw to read Tx BMI registers and expose
them through the xstats interface.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/fman/fman_hw.c | 2 --
drivers/bus/dpaa/include/fman.h | 24 ++++++++++++++++++++++++
drivers/net/dpaa/dpaa_ethdev.c | 10 +++++++++-
drivers/net/dpaa/dpaa_ethdev.h | 11 +++++++++--
4 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/drivers/bus/dpaa/base/fman/fman_hw.c b/drivers/bus/dpaa/base/fman/fman_hw.c
index ce68581555..aab04bf76a 100644
--- a/drivers/bus/dpaa/base/fman/fman_hw.c
+++ b/drivers/bus/dpaa/base/fman/fman_hw.c
@@ -301,7 +301,6 @@ fman_if_bmi_stats_enable(struct fman_if *p)
uint32_t tmp;
tmp = in_be32(®s->fmbm_rstc);
-
tmp |= FMAN_BMI_COUNTERS_EN;
out_be32(®s->fmbm_rstc, tmp);
@@ -315,7 +314,6 @@ fman_if_bmi_stats_disable(struct fman_if *p)
uint32_t tmp;
tmp = in_be32(®s->fmbm_rstc);
-
tmp &= ~FMAN_BMI_COUNTERS_EN;
out_be32(®s->fmbm_rstc, tmp);
diff --git a/drivers/bus/dpaa/include/fman.h b/drivers/bus/dpaa/include/fman.h
index a248edf4d8..2bddf489b8 100644
--- a/drivers/bus/dpaa/include/fman.h
+++ b/drivers/bus/dpaa/include/fman.h
@@ -306,6 +306,21 @@ struct tx_bmi_regs {
uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine*/
uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale*/
uint32_t fmbm_trlmt; /**< Tx Rate Limiter*/
+ uint32_t reserved0034[0x73];/**< (0x0034 0x01FF) */
+ uint32_t fmbm_tstc; /**< Tx Statistics Counters*/
+ uint32_t fmbm_tfrc; /**< Tx Frame Counter*/
+ uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter*/
+ uint32_t fmbm_tfledc; /**< Tx Frames Length Error Discard*/
+ uint32_t fmbm_tfufdc; /**< Tx Frames Unsupported Format*/
+ uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */
+ uint32_t reserved0218[0x1a];/**< (0x0218 0x027F) */
+ uint32_t fmbm_tpc; /**< Tx Performance Counters*/
+ uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters */
+ uint32_t fmbm_tccn; /**< Tx Cycle Counter*/
+ uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter */
+ uint32_t fmbm_ttcquc; /**< Tx Transmit Confirm Queue Utilization Counter*/
+ uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter */
+ uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter */
};
/* Description FM RTC timer alarm */
@@ -468,6 +483,15 @@ struct __fman_if {
void *qmi_map;
};
+#define MEMMAC_REG_OFFSET(reg) offsetof(struct memac_regs, reg)
+#define BMI_RX_REG_OFFSET(reg) offsetof(struct rx_bmi_regs, reg)
+#define BMI_TX_REG_OFFSET(reg) offsetof(struct tx_bmi_regs, reg)
+
+#define FMAN_IF_BMI_RX_STAT_OFFSET_START BMI_RX_REG_OFFSET(fmbm_rfrc)
+#define FMAN_IF_BMI_RX_STAT_OFFSET_END BMI_RX_REG_OFFSET(fmbm_rbdc)
+#define FMAN_IF_BMI_TX_STAT_OFFSET_START BMI_TX_REG_OFFSET(fmbm_tfrc)
+#define FMAN_IF_BMI_TX_STAT_OFFSET_END BMI_TX_REG_OFFSET(fmbm_tbdc)
+
/* And this is the base list node that the interfaces are added to. (See
* fman_if_enable_all_rx() below for an example of its use.)
*/
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 9f976d179b..8fb2e33e0a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2016 Freescale Semiconductor, Inc. All rights reserved.
- * Copyright 2017-2020,2022-2025 NXP
+ * Copyright 2017-2020,2022-2026 NXP
*
*/
/* System headers */
@@ -143,6 +143,14 @@ static const struct rte_dpaa_xstats_name_off dpaa_xstats_strings[] = {
offsetof(struct dpaa_if_rx_bmi_stats, fmbm_rodc)},
{"rx_buf_diallocate",
offsetof(struct dpaa_if_rx_bmi_stats, fmbm_rbdc)},
+ {"tx_bad_frames_count",
+ offsetof(struct dpaa_if_tx_bmi_stats, fmbm_tfdc)},
+ {"tx_frame_length_discard",
+ offsetof(struct dpaa_if_tx_bmi_stats, fmbm_tfledc)},
+ {"tx_frames_unsupported_format",
+ offsetof(struct dpaa_if_tx_bmi_stats, fmbm_tfufdc)},
+ {"tx_buf_diallocate",
+ offsetof(struct dpaa_if_tx_bmi_stats, fmbm_tbdc)},
};
static struct rte_dpaa_driver rte_dpaa_pmd;
diff --git a/drivers/net/dpaa/dpaa_ethdev.h b/drivers/net/dpaa/dpaa_ethdev.h
index f400030a5c..d342d98f23 100644
--- a/drivers/net/dpaa/dpaa_ethdev.h
+++ b/drivers/net/dpaa/dpaa_ethdev.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2014-2016 Freescale Semiconductor, Inc. All rights reserved.
- * Copyright 2017-2024 NXP
+ * Copyright 2017-2026 NXP
*
*/
#ifndef __DPAA_ETHDEV_H__
@@ -234,7 +234,6 @@ dpaa_rx_cb_atomic(void *event,
void **bufs);
struct dpaa_if_rx_bmi_stats {
- uint32_t fmbm_rstc; /**< Rx Statistics Counters*/
uint32_t fmbm_rfrc; /**< Rx Frame Counter*/
uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/
uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/
@@ -245,6 +244,14 @@ struct dpaa_if_rx_bmi_stats {
uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter*/
};
+struct dpaa_if_tx_bmi_stats {
+ uint32_t fmbm_tfrc; /**< Tx Frame Counter*/
+ uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter*/
+ uint32_t fmbm_tfledc; /**< Tx Frames Length Error Discard*/
+ uint32_t fmbm_tfufdc; /**< Tx Frames Unsupported Format*/
+ uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */
+};
+
int
dpaa_tx_conf_queue_init(struct qman_fq *fq);
--
2.25.1
^ permalink raw reply related
* [PATCH v4 04/19] drivers: add process-type guards for secondary process
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Prashant Gupta
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Prashant Gupta <prashant.gupta_3@nxp.com>
Add RTE_PROC_PRIMARY checks in device initialization paths for
net/dpaa, crypto/dpaa_sec and dma/dpaa drivers. Secondary
processes should skip hardware initialization to prevent
segfaults when accessing hardware registers that are only
mapped in the primary process.
Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com>
---
drivers/crypto/dpaa_sec/dpaa_sec.c | 3 ---
drivers/dma/dpaa/dpaa_qdma.c | 23 +++++++++++++++++++++++
drivers/net/dpaa/dpaa_ethdev.c | 3 +++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.c b/drivers/crypto/dpaa_sec/dpaa_sec.c
index 65bbd38b17..36f5819b0e 100644
--- a/drivers/crypto/dpaa_sec/dpaa_sec.c
+++ b/drivers/crypto/dpaa_sec/dpaa_sec.c
@@ -3783,9 +3783,6 @@ cryptodev_dpaa_sec_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
RTE_DPAA_MAX_NB_SEC_QPS,
};
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return 0;
-
snprintf(cryptodev_name, sizeof(cryptodev_name), "%s", dpaa_dev->name);
cryptodev = rte_cryptodev_pmd_create(cryptodev_name, &dpaa_dev->device, &init_params);
diff --git a/drivers/dma/dpaa/dpaa_qdma.c b/drivers/dma/dpaa/dpaa_qdma.c
index 74e23d2ee5..af6083d2fe 100644
--- a/drivers/dma/dpaa/dpaa_qdma.c
+++ b/drivers/dma/dpaa/dpaa_qdma.c
@@ -1330,11 +1330,34 @@ dpaa_qdma_init(struct rte_dma_dev *dmadev)
int ret;
uint32_t i, j, k;
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return -ENOTSUP;
+
if (dpaa_get_devargs(dmadev->device->devargs, DPAA_DMA_ERROR_CHECK)) {
s_hw_err_check = true;
DPAA_QDMA_INFO("Enable DMA error checks");
}
+ if (getenv("DPAA_QDMA_DATA_VALIDATION"))
+ s_data_validation = 1;
+
+ if (getenv("DPAA_QDMA_HW_ERR_CHECK"))
+ s_hw_err_check = 1;
+
+ char *penv = getenv("DPAA_QDMA_SG_ENABLE");
+ if (penv)
+ s_sg_enable = atoi(penv);
+
+ penv = getenv("DPAA_QDMA_SG_MAX_ENTRY_SIZE");
+ if (penv)
+ s_sg_max_entry_sz = atoi(penv);
+
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+ penv = getenv("DPAA_QDMA_PCI_READ");
+ if (penv)
+ s_pci_read = atoi(penv);
+#endif
+
fsl_qdma->n_queues = QDMA_QUEUES * QDMA_BLOCKS;
fsl_qdma->num_blocks = QDMA_BLOCKS;
fsl_qdma->block_offset = QDMA_BLOCK_OFFSET;
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 8fb2e33e0a..42ab9679d1 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2686,6 +2686,9 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
PMD_INIT_FUNC_TRACE();
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
eth_dev = dpaa_dev->eth_dev;
dpaa_eth_dev_close(eth_dev);
ret = rte_eth_dev_release_port(eth_dev);
--
2.25.1
^ permalink raw reply related
* [PATCH v4 05/19] bus/dpaa: define helpers for qman channel and wq
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Add inline helper functions to extract channel and work queue
from a frame queue descriptor, replacing open-coded bit
manipulation throughout the driver.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 14 ++------------
drivers/bus/dpaa/base/qbman/qman.h | 23 ++++++++++++++++++++++-
2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 5534e1846c..c9a8ec34a5 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -2704,14 +2704,6 @@ int qman_delete_cgr(struct qman_cgr *cgr)
return ret;
}
-#define GENMASK(h, l) \
- (((~0U) >> (sizeof(unsigned int) * 8 - ((h) - (l) + 1))) << (l))
-
-/* 'fqid' is a 24-bit field in every h/w descriptor */
-#define QM_FQID_MASK GENMASK(23, 0)
-#define qm_fqid_set(p, v) ((p)->fqid = cpu_to_be32((v) & QM_FQID_MASK))
-#define qm_fqid_get(p) (be32_to_cpu((p)->fqid) & QM_FQID_MASK)
-
static int
_qm_mr_consume_and_match_verb(struct qm_portal *p, int v)
{
@@ -2798,7 +2790,6 @@ qman_shutdown_fq(u32 fqid)
u32 res;
u8 state;
u32 channel, wq;
- u16 dest_wq;
DPAA_BUS_DEBUG("In shutdown for queue = %x", fqid);
p = get_affine_portal();
@@ -2828,9 +2819,8 @@ qman_shutdown_fq(u32 fqid)
}
/* Need to store these since the MCR gets reused */
- dest_wq = be16_to_cpu(mcr->queryfq.fqd.dest_wq);
- channel = dest_wq & 0x7;
- wq = dest_wq >> 3;
+ channel = qm_fqd_get_chan(&mcr->queryfq.fqd);
+ wq = qm_fqd_get_wq(&mcr->queryfq.fqd);
switch (state) {
case QM_MCR_NP_STATE_TEN_SCHED:
diff --git a/drivers/bus/dpaa/base/qbman/qman.h b/drivers/bus/dpaa/base/qbman/qman.h
index 43a16d1e3b..bd97689a91 100644
--- a/drivers/bus/dpaa/base/qbman/qman.h
+++ b/drivers/bus/dpaa/base/qbman/qman.h
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017 NXP
+ * Copyright 2017,2026 NXP
*
*/
#include "qman_priv.h"
+#define GENMASK(h, l) \
+ (((~0U) >> (sizeof(u32) * 8 - ((h) - (l) + 1))) << (l))
+
/***************************/
/* Portal register assists */
/***************************/
@@ -42,6 +45,14 @@
#define QM_CL_RR0 0x3900
#define QM_CL_RR1 0x3940
+#define QM_FQD_CHAN_OFF 3
+#define QM_FQD_WQ_MASK GENMASK(2, 0)
+/* 'fqid' is a 24-bit field in every h/w descriptor */
+#define QM_FQID_MASK GENMASK(23, 0)
+
+#define qm_fqid_set(p, v) ((p)->fqid = cpu_to_be32((v) & QM_FQID_MASK))
+#define qm_fqid_get(p) (be32_to_cpu((p)->fqid) & QM_FQID_MASK)
+
/* BTW, the drivers (and h/w programming model) already obtain the required
* synchronisation for portal accesses via lwsync(), hwsync(), and
* data-dependencies. Use of barrier()s or other order-preserving primitives
@@ -911,3 +922,13 @@ static inline void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n,
__qm_out(&portal->addr, QM_REG_ISR + (n << 2), val);
#endif
}
+
+static inline int qm_fqd_get_chan(const struct qm_fqd *fqd)
+{
+ return be16_to_cpu(fqd->dest_wq) >> QM_FQD_CHAN_OFF;
+}
+
+static inline int qm_fqd_get_wq(const struct qm_fqd *fqd)
+{
+ return be16_to_cpu(fqd->dest_wq) & QM_FQD_WQ_MASK;
+}
--
2.25.1
^ permalink raw reply related
* [PATCH v4 06/19] drivers: shutdown DPAA FQ by fq descriptor
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Pass the full FQ descriptor to qman_shutdown_fq() instead of
just the fqid, so that channel-affine portals can be correctly
accessed when shutting down push-mode Rx queues.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 9 +++++----
drivers/bus/dpaa/include/fsl_qman.h | 11 ++++++++++-
drivers/net/dpaa/dpaa_ethdev.c | 7 +++++++
3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index c9a8ec34a5..dc8aeaa568 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -2781,18 +2781,19 @@ qm_mc_result_timeout(struct qm_portal *portal,
RTE_EXPORT_INTERNAL_SYMBOL(qman_shutdown_fq)
int
-qman_shutdown_fq(u32 fqid)
+qman_shutdown_fq(struct qman_fq *fq)
{
- struct qman_portal *p;
+ struct qman_portal *p = fq->qp;
struct qm_mc_command *mcc;
struct qm_mc_result *mcr;
int orl_empty, drain = 0, ret = 0;
- u32 res;
+ u32 res, fqid = fq->fqid;
u8 state;
u32 channel, wq;
DPAA_BUS_DEBUG("In shutdown for queue = %x", fqid);
- p = get_affine_portal();
+ if (!p)
+ p = get_affine_portal();
/* Determine the state of the FQID */
mcc = qm_mc_start(&p->p);
mcc->queryfq_np.fqid = cpu_to_be32(fqid);
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index 82269cdf99..673859ed2e 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1896,7 +1896,16 @@ static inline void qman_release_fqid(u32 fqid)
void qman_seed_fqid_range(u32 fqid, unsigned int count);
__rte_internal
-int qman_shutdown_fq(u32 fqid);
+int qman_shutdown_fq(struct qman_fq *fq);
+
+static inline int qman_shutdown_fq_by_fqid(u32 fqid)
+{
+ struct qman_fq fq;
+
+ memset(&fq, 0, sizeof(struct qman_fq));
+ fq.fqid = fqid;
+ return qman_shutdown_fq(&fq);
+}
/**
* qman_reserve_fqid_range - Reserve the specified range of frame queue IDs
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 42ab9679d1..94758c2748 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2364,6 +2364,13 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
vsp_id = dev_vspids[loop];
+ /* Shutdown FQ before configure to clean the queue */
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret < 0) {
+ DPAA_PMD_ERR("Failed shutdown %s:rxq-%d-fqid = 0x%08x",
+ dpaa_intf->name, loop, fqid);
+ }
+
if (dpaa_intf->cgr_rx)
dpaa_intf->cgr_rx[loop].cgrid = cgrid[loop];
--
2.25.1
^ permalink raw reply related
* [PATCH v4 07/19] bus/dpaa: improve FQ shutdown with channel validation
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Fix hardcoded channel range check by using DTS-derived pool
channel start/end values. Add validation that the portal's
affine channel matches the FQ's channel for pool-channel FQs,
and only restore SDQCR when it was actually changed.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 54 ++++++++++-------------
drivers/bus/dpaa/base/qbman/qman_driver.c | 29 ++++++++++--
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 2 +
drivers/bus/dpaa/include/fsl_qman.h | 8 ++--
4 files changed, 54 insertions(+), 39 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index dc8aeaa568..42618c1ab4 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -2789,7 +2789,7 @@ qman_shutdown_fq(struct qman_fq *fq)
int orl_empty, drain = 0, ret = 0;
u32 res, fqid = fq->fqid;
u8 state;
- u32 channel, wq;
+ u16 channel;
DPAA_BUS_DEBUG("In shutdown for queue = %x", fqid);
if (!p)
@@ -2803,9 +2803,10 @@ qman_shutdown_fq(struct qman_fq *fq)
ret = -ETIMEDOUT;
goto out;
}
+
state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK;
if (state == QM_MCR_NP_STATE_OOS) {
- DPAA_BUS_ERR("Already in OOS");
+ DPAA_BUS_DEBUG("fqid(0x%x) Already in OOS", fqid);
goto out; /* Already OOS, no need to do anymore checks */
}
@@ -2821,7 +2822,6 @@ qman_shutdown_fq(struct qman_fq *fq)
/* Need to store these since the MCR gets reused */
channel = qm_fqd_get_chan(&mcr->queryfq.fqd);
- wq = qm_fqd_get_wq(&mcr->queryfq.fqd);
switch (state) {
case QM_MCR_NP_STATE_TEN_SCHED:
@@ -2840,10 +2840,9 @@ qman_shutdown_fq(struct qman_fq *fq)
}
res = mcr->result; /* Make a copy as we reuse MCR below */
- if (res == QM_MCR_RESULT_OK)
+ if (res == QM_MCR_RESULT_OK) {
drain_mr_fqrni(&p->p);
-
- if (res == QM_MCR_RESULT_PENDING) {
+ } else if (res == QM_MCR_RESULT_PENDING) {
/*
* Need to wait for the FQRN in the message ring, which
* will only occur once the FQ has been drained. In
@@ -2851,35 +2850,31 @@ qman_shutdown_fq(struct qman_fq *fq)
* to dequeue from the channel the FQ is scheduled on
*/
int found_fqrn = 0;
+ const u16 pool_ch_start = dpaa_get_qm_channel_pool();
+ const u16 pool_ch_end = pool_ch_start + dpaa_get_qm_channel_pool_num();
+ u32 sdqcr = p->sdqcr;
/* Flag that we need to drain FQ */
drain = 1;
- __maybe_unused u16 dequeue_wq = 0;
- if (channel >= qm_channel_pool1 &&
- channel < (u16)(qm_channel_pool1 + 15)) {
+ if (channel >= pool_ch_start && channel < pool_ch_end) {
/* Pool channel, enable the bit in the portal */
- dequeue_wq = (channel -
- qm_channel_pool1 + 1) << 4 | wq;
- } else if (channel < qm_channel_pool1) {
+ if (p->config->channel != channel) {
+ DPAA_BUS_ERR("Portal affine channel(0x%04x) != wq channel(0x%04x)",
+ p->config->channel, channel);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else if (channel < pool_ch_start) {
/* Dedicated channel */
- dequeue_wq = wq;
+ sdqcr = QM_SDQCR_TYPE_ACTIVE | QM_SDQCR_CHANNELS_DEDICATED;
+ qm_dqrr_sdqcr_set(&p->p, sdqcr);
} else {
- DPAA_BUS_ERR("Can't recover FQ 0x%x, ch: 0x%x",
+ DPAA_BUS_ERR("Can't recover FQ 0x%x, Invalid channel: 0x%x",
fqid, channel);
ret = -EBUSY;
goto out;
}
- /* Set the sdqcr to drain this channel */
- if (channel < qm_channel_pool1)
- qm_dqrr_sdqcr_set(&p->p,
- QM_SDQCR_TYPE_ACTIVE |
- QM_SDQCR_CHANNELS_DEDICATED);
- else
- qm_dqrr_sdqcr_set(&p->p,
- QM_SDQCR_TYPE_ACTIVE |
- QM_SDQCR_CHANNELS_POOL_CONV
- (channel));
do {
/* Keep draining DQRR while checking the MR*/
qm_dqrr_drain_nomatch(&p->p);
@@ -2889,13 +2884,10 @@ qman_shutdown_fq(struct qman_fq *fq)
cpu_relax();
} while (!found_fqrn);
/* Restore SDQCR */
- qm_dqrr_sdqcr_set(&p->p,
- p->sdqcr);
- }
- if (res != QM_MCR_RESULT_OK &&
- res != QM_MCR_RESULT_PENDING) {
- DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x",
- fqid, res);
+ if (sdqcr != p->sdqcr)
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+ } else {
+ DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x", fqid, res);
ret = -EIO;
goto out;
}
diff --git a/drivers/bus/dpaa/base/qbman/qman_driver.c b/drivers/bus/dpaa/base/qbman/qman_driver.c
index 3bab8b8337..0fcaa270ce 100644
--- a/drivers/bus/dpaa/base/qbman/qman_driver.c
+++ b/drivers/bus/dpaa/base/qbman/qman_driver.c
@@ -17,9 +17,10 @@
* where CCSR isn't available).
*/
u16 qman_ip_rev;
-u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
-u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
-u16 qm_channel_pme = QMAN_CHANNEL_PME;
+static u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
+static u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
+static u16 qm_channel_pme = QMAN_CHANNEL_PME;
+static u16 qm_channel_pool_num;
/* Ccsr map address to access ccsrbased register */
static void *qman_ccsr_map;
@@ -65,6 +66,11 @@ u16 dpaa_get_qm_channel_pool(void)
return qm_channel_pool1;
}
+u16 dpaa_get_qm_channel_pool_num(void)
+{
+ return qm_channel_pool_num;
+}
+
static int fsl_qman_portal_init(uint32_t index, int is_shared)
{
struct qman_portal *portal;
@@ -275,7 +281,7 @@ int qman_global_init(void)
uint64_t phys_addr;
uint64_t regs_size;
const u32 *clk;
-
+ u16 pool_channel;
static int done;
if (done)
@@ -336,6 +342,21 @@ int qman_global_init(void)
return -EINVAL;
}
+ if (lenp != sizeof(rte_be32_t) * 2) {
+ pr_err("pool-channel-range should have 2 items.\n");
+ return -EINVAL;
+ }
+ pool_channel = rte_be_to_cpu_32(chanid[0]);
+ qm_channel_pool_num = rte_be_to_cpu_32(chanid[1]);
+
+ if (pool_channel != qm_channel_pool1) {
+ pr_warn("Pool channel(%04x) configured != default(0x%04x)\n",
+ pool_channel, qm_channel_pool1);
+ }
+ qm_channel_pool1 = pool_channel;
+ pr_debug("Pool channel starts from 0x%04x, number=%d, lenp:%zu\n",
+ qm_channel_pool1, qm_channel_pool_num, lenp);
+
/* get ccsr base */
dt_node = of_find_compatible_node(NULL, NULL, "fsl,qman");
if (!dt_node) {
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 522cdca27e..52abec2b4c 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2025 Red Hat, Inc.
+ * Copyright 2026 NXP
*/
#include <eal_export.h>
@@ -94,6 +95,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(qman_create_cgr)
RTE_EXPORT_INTERNAL_SYMBOL(qman_delete_cgr)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_caam)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_pool_num)
RTE_EXPORT_INTERNAL_SYMBOL(qman_thread_fd)
RTE_EXPORT_INTERNAL_SYMBOL(qman_thread_irq)
RTE_EXPORT_INTERNAL_SYMBOL(qman_fq_portal_thread_irq)
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index 673859ed2e..bd46207232 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2019-2022 NXP
+ * Copyright 2019-2022, 2026 NXP
*
*/
@@ -35,9 +35,6 @@ extern "C" {
#define QMAN_CHANNEL_POOL1_REV3 0x401
#define QMAN_CHANNEL_CAAM_REV3 0x840
#define QMAN_CHANNEL_PME_REV3 0x860
-extern u16 qm_channel_pool1;
-extern u16 qm_channel_caam;
-extern u16 qm_channel_pme;
enum qm_dc_portal {
qm_dc_portal_fman0 = 0,
qm_dc_portal_fman1 = 1,
@@ -51,6 +48,9 @@ u16 dpaa_get_qm_channel_caam(void);
__rte_internal
u16 dpaa_get_qm_channel_pool(void);
+__rte_internal
+u16 dpaa_get_qm_channel_pool_num(void);
+
/* Portal processing (interrupt) sources */
#define QM_PIRQ_CCSCI 0x00200000 /* CEETM Congestion State Change */
#define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */
--
2.25.1
^ permalink raw reply related
* [PATCH v4 08/19] bus/dpaa: enhance DPAA FQ shutdown
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Gagandeep Singh
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Gagandeep Singh <g.singh@nxp.com>
Improve the FQ shutdown sequence to handle edge cases more
robustly, including better handling of ORL (Order Restoration
List) presence and improved error recovery paths.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 80 ++++++++++++++++++++++--------
1 file changed, 59 insertions(+), 21 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 42618c1ab4..ba7db78ca0 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017,2019-2025 NXP
+ * Copyright 2017,2019-2026 NXP
*
*/
@@ -2840,9 +2840,10 @@ qman_shutdown_fq(struct qman_fq *fq)
}
res = mcr->result; /* Make a copy as we reuse MCR below */
- if (res == QM_MCR_RESULT_OK) {
+ if (res == QM_MCR_RESULT_OK)
drain_mr_fqrni(&p->p);
- } else if (res == QM_MCR_RESULT_PENDING) {
+
+ if (res == QM_MCR_RESULT_PENDING) {
/*
* Need to wait for the FQRN in the message ring, which
* will only occur once the FQ has been drained. In
@@ -2850,28 +2851,29 @@ qman_shutdown_fq(struct qman_fq *fq)
* to dequeue from the channel the FQ is scheduled on
*/
int found_fqrn = 0;
- const u16 pool_ch_start = dpaa_get_qm_channel_pool();
- const u16 pool_ch_end = pool_ch_start + dpaa_get_qm_channel_pool_num();
- u32 sdqcr = p->sdqcr;
/* Flag that we need to drain FQ */
drain = 1;
+ const u16 pool_ch_start = dpaa_get_qm_channel_pool();
+ const u16 pool_ch_end = pool_ch_start +
+ dpaa_get_qm_channel_pool_num();
if (channel >= pool_ch_start && channel < pool_ch_end) {
- /* Pool channel, enable the bit in the portal */
+ /* Pool channel - must use affine portal */
if (p->config->channel != channel) {
- DPAA_BUS_ERR("Portal affine channel(0x%04x) != wq channel(0x%04x)",
+ DPAA_BUS_ERR("Portal ch(0x%04x) != FQ ch(0x%04x)",
p->config->channel, channel);
ret = -EINVAL;
goto out;
}
} else if (channel < pool_ch_start) {
/* Dedicated channel */
- sdqcr = QM_SDQCR_TYPE_ACTIVE | QM_SDQCR_CHANNELS_DEDICATED;
- qm_dqrr_sdqcr_set(&p->p, sdqcr);
+ qm_dqrr_sdqcr_set(&p->p,
+ QM_SDQCR_TYPE_ACTIVE |
+ QM_SDQCR_CHANNELS_DEDICATED);
} else {
- DPAA_BUS_ERR("Can't recover FQ 0x%x, Invalid channel: 0x%x",
- fqid, channel);
+ DPAA_BUS_ERR("Invalid channel 0x%x for FQ 0x%x",
+ channel, fqid);
ret = -EBUSY;
goto out;
}
@@ -2879,15 +2881,16 @@ qman_shutdown_fq(struct qman_fq *fq)
/* Keep draining DQRR while checking the MR*/
qm_dqrr_drain_nomatch(&p->p);
/* Process message ring too */
- found_fqrn = qm_mr_drain(&p->p,
- FQRN);
+ found_fqrn = qm_mr_drain(&p->p, FQRN);
cpu_relax();
} while (!found_fqrn);
- /* Restore SDQCR */
- if (sdqcr != p->sdqcr)
- qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
- } else {
- DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x", fqid, res);
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+
+ }
+ if (res != QM_MCR_RESULT_OK &&
+ res != QM_MCR_RESULT_PENDING) {
+ DPAA_BUS_ERR("retire_fq failed: FQ 0x%x, res=0x%x",
+ fqid, res);
ret = -EIO;
goto out;
}
@@ -2930,7 +2933,7 @@ qman_shutdown_fq(struct qman_fq *fq)
if (mcr->result != QM_MCR_RESULT_OK) {
DPAA_BUS_ERR("OOS after drain fail: FQ 0x%x (0x%x)",
- fqid, mcr->result);
+ fqid, mcr->result);
ret = -EIO;
goto out;
}
@@ -2949,7 +2952,7 @@ qman_shutdown_fq(struct qman_fq *fq)
if (mcr->result != QM_MCR_RESULT_OK) {
DPAA_BUS_ERR("OOS fail: FQ 0x%x (0x%x)",
- fqid, mcr->result);
+ fqid, mcr->result);
ret = -EIO;
goto out;
}
@@ -2966,3 +2969,38 @@ qman_shutdown_fq(struct qman_fq *fq)
out:
return ret;
}
+
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid)
+{
+ struct qman_fq fq = {
+ .fqid = 1
+ };
+ struct qm_mcr_queryfq_np np;
+ struct qm_fqd fqd;
+ int err;
+
+ do {
+ err = qman_query_fq_np(&fq, &np);
+ if (err == -ERANGE) {
+ DPAA_BUS_INFO("No FQ found with cgrid(0x%x)", cgrid);
+ return err;
+ } else if (err) {
+ DPAA_BUS_WARN("Failed(%d) to Query np FQ(fqid=0x%x)", err, fq.fqid);
+ return err;
+ }
+ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) {
+ err = qman_query_fq(&fq, &fqd);
+ if (err) {
+ DPAA_BUS_WARN("Failed(%d) to Query FQ(fqid=0x%x)", err, fq.fqid);
+ } else if ((fqd.fq_ctrl & QM_FQCTRL_CGE) && fqd.cgid == cgrid) {
+ if (fqid)
+ *fqid = fq.fqid;
+ return 0;
+ }
+ }
+ /* Move to the next FQID */
+ fq.fqid++;
+ } while (1);
+
+ return -ENODEV;
+}
--
2.25.1
^ permalink raw reply related
* [PATCH v4 09/19] drivers: add DPAA cgrid cleanup support
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Add qman_find_fq_by_cgid() to find frame queues associated with
a given CGID. This allows the driver to verify that all FQs
using a CGR are shut down before releasing the CGR ID, preventing
use-after-free of CGR resources.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_qman.h | 3 +++
drivers/net/dpaa/dpaa_ethdev.c | 29 ++++++++++++++++++++++--
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 52abec2b4c..514ab7b1f1 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -56,6 +56,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(qman_reserve_fqid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_pool_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_cgrid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_release_cgrid_range)
+RTE_EXPORT_INTERNAL_SYMBOL(qman_find_fq_by_cgrid)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_enable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_intr_disable)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_ioctl_version_number)
diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h
index bd46207232..20321ed355 100644
--- a/drivers/bus/dpaa/include/fsl_qman.h
+++ b/drivers/bus/dpaa/include/fsl_qman.h
@@ -1907,6 +1907,9 @@ static inline int qman_shutdown_fq_by_fqid(u32 fqid)
return qman_shutdown_fq(&fq);
}
+__rte_internal
+int qman_find_fq_by_cgrid(u32 cgrid, u32 *fqid);
+
/**
* qman_reserve_fqid_range - Reserve the specified range of frame queue IDs
* @fqid: the base FQID of the range to deallocate
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 94758c2748..ab5a50e760 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -513,7 +513,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
struct rte_eth_link *link = &dev->data->dev_link;
struct dpaa_if *dpaa_intf = dev->data->dev_private;
struct qman_fq *fq;
- int loop;
+ uint32_t fqid, loop;
int ret;
PMD_INIT_FUNC_TRACE();
@@ -576,28 +576,53 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ /** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
if (dpaa_intf->cgr_rx) {
for (loop = 0; loop < dpaa_intf->nb_rx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_rx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with rx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_rx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_rx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete rxq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_rx[0].cgrid, dpaa_intf->nb_rx_queues);
rte_free(dpaa_intf->cgr_rx);
dpaa_intf->cgr_rx = NULL;
}
/* Release TX congestion Groups */
if (dpaa_intf->cgr_tx) {
- for (loop = 0; loop < MAX_DPAA_CORES; loop++) {
+ for (loop = 0; loop < dpaa_intf->nb_tx_queues; loop++) {
+ ret = qman_find_fq_by_cgrid(dpaa_intf->cgr_tx[loop].cgrid, &fqid);
+ if (!ret) {
+ /** Should be FQ not cleaned in previous program.*/
+ DPAA_PMD_DEBUG("FQ(fqid=0x%x) with tx cgid=%d is still alive?",
+ fqid, dpaa_intf->cgr_tx[loop].cgrid);
+ ret = qman_shutdown_fq_by_fqid(fqid);
+ if (ret) {
+ DPAA_PMD_WARN("Failed(%d) to shutdown fq(fqid=0x%x)",
+ ret, fqid);
+ }
+ }
ret = qman_delete_cgr(&dpaa_intf->cgr_tx[loop]);
if (ret) {
DPAA_PMD_WARN("%s: delete txq%d's cgr err(%d)",
dev->data->name, loop, ret);
}
}
+ qman_release_cgrid_range(dpaa_intf->cgr_tx[0].cgrid, dpaa_intf->nb_tx_queues);
rte_free(dpaa_intf->cgr_tx);
dpaa_intf->cgr_tx = NULL;
}
--
2.25.1
^ permalink raw reply related
* [PATCH v4 10/19] net/dpaa: clean Tx confirmation FQ on device stop
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
Ensure the Tx confirmation FQ is also cleaned up during device
stop, preventing stale FQ state on subsequent device restarts.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index ab5a50e760..314237b25a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -575,6 +575,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* release configuration memory */
rte_free(dpaa_intf->fc_conf);
+ dpaa_intf->fc_conf = NULL;
/** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
@@ -644,6 +645,10 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
+
+ rte_free(dpaa_intf->tx_conf_queues);
+ dpaa_intf->tx_conf_queues = NULL;
+
if (dpaa_intf->port_handle) {
ret = dpaa_fm_deconfig(dpaa_intf, fif);
if (ret) {
@@ -2538,6 +2543,8 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
return 0;
free_tx:
+ rte_free(dpaa_intf->tx_conf_queues);
+ dpaa_intf->tx_conf_queues = NULL;
rte_free(dpaa_intf->tx_queues);
dpaa_intf->tx_queues = NULL;
dpaa_intf->nb_tx_queues = 0;
--
2.25.1
^ permalink raw reply related
* [PATCH v4 11/19] net/dpaa: remove redundant FQ shutdown from Rx queue setup
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
Remove the redundant qman_shutdown_fq() call from
dpaa_eth_rx_queue_setup(). The FQ is shut down during device stop,
so calling it again at queue setup time is unnecessary and may
interfere with a clean queue initialization.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 314237b25a..5ef3fcdb48 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1158,9 +1158,6 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
DPAA_PMD_INFO("Rx queue setup for queue index: %d fq_id (0x%x)",
queue_idx, rxq->fqid);
- /* Shutdown FQ before configure */
- qman_shutdown_fq(rxq->fqid);
-
if (!fif->num_profiles) {
if (dpaa_intf->bp_info && dpaa_intf->bp_info->bp &&
dpaa_intf->bp_info->mp != mp) {
--
2.25.1
^ permalink raw reply related
* [PATCH v4 12/19] net/dpaa: optimize FM deconfig
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
Consolidate FM deconfiguration to avoid duplicate calls.
Move the fm_deconfig call to a single location and remove
redundant checks in the device close path.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 27 +++++++++++++++++++++++----
drivers/net/dpaa/dpaa_flow.c | 9 +++++----
2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 5ef3fcdb48..2e3757ca03 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -528,10 +528,12 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
/* DPAA FM deconfig */
if (!(default_q || fmc_q)) {
- ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
- if (ret) {
- DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
- dev->data->name, ret);
+ if (dpaa_intf->port_handle) {
+ ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
+ if (ret) {
+ DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
+ dev->data->name, ret);
+ }
}
}
@@ -577,6 +579,23 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
rte_free(dpaa_intf->fc_conf);
dpaa_intf->fc_conf = NULL;
+ /** For FMCLESS mode of share MAC, deconfig FM to direct
+ * ingress traffic to kernel before fq shutdown.
+ */
+ if (!(default_q || fmc_q) && dpaa_intf->port_handle) {
+ ret = dpaa_fm_deconfig(dpaa_intf, dev->process_private);
+ if (ret) {
+ DPAA_PMD_WARN("%s: FM deconfig failed(%d)",
+ dev->data->name, ret);
+ }
+ }
+ if (fif->num_profiles) {
+ ret = dpaa_port_vsp_cleanup(dpaa_intf, fif);
+ if (ret) {
+ DPAA_PMD_WARN("%s: cleanup VSP failed(%d)",
+ dev->data->name, ret);
+ }
+ }
/** Release congestion Groups after releasing FQIDs*/
/* Release RX congestion Groups */
if (dpaa_intf->cgr_rx) {
diff --git a/drivers/net/dpaa/dpaa_flow.c b/drivers/net/dpaa/dpaa_flow.c
index 417b9b6fbb..559850ced7 100644
--- a/drivers/net/dpaa/dpaa_flow.c
+++ b/drivers/net/dpaa/dpaa_flow.c
@@ -724,6 +724,9 @@ int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf,
PMD_INIT_FUNC_TRACE();
+ if (!dpaa_intf->port_handle)
+ return 0;
+
/* FM PORT Disable */
ret = fm_port_disable(dpaa_intf->port_handle);
if (ret != E_OK) {
@@ -783,10 +786,8 @@ int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
unsigned int i = 0;
PMD_INIT_FUNC_TRACE();
- if (dpaa_intf->port_handle) {
- if (dpaa_fm_deconfig(dpaa_intf, fif))
- DPAA_PMD_ERR("DPAA FM deconfig failed");
- }
+ if (dpaa_fm_deconfig(dpaa_intf, fif))
+ DPAA_PMD_ERR("DPAA FM deconfig failed");
if (!dev->data->nb_rx_queues)
return 0;
--
2.25.1
^ permalink raw reply related
* [PATCH v4 13/19] bus/dpaa: improve log macro and fix bus detection
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
Replace DPAA_BUS_LOG(LEVEL, ...) calls with shorthand macros
(DPAA_BUS_INFO, DPAA_BUS_ERR, DPAA_BUS_WARN, DPAA_BUS_DEBUG) for
consistency across the driver.
Move bus detection (sysfs path check), portal key creation and
dpaa_bus.detected guard into dpaa_bus_dev_compare() so that bus
probe is properly gated on hardware presence.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/fman/fman.c | 9 ++++-----
drivers/bus/dpaa/dpaa_bus.c | 33 +++++++++++++++++++++++++------
2 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/drivers/bus/dpaa/base/fman/fman.c b/drivers/bus/dpaa/base/fman/fman.c
index 55f466d751..67f77265ca 100644
--- a/drivers/bus/dpaa/base/fman/fman.c
+++ b/drivers/bus/dpaa/base/fman/fman.c
@@ -119,7 +119,7 @@ _fman_init(const struct device_node *fman_node, int fd)
ip_rev_1 = in_be32((uint8_t *)fman->ccsr_vir + FMAN_IP_REV_1);
fman->ip_rev = ip_rev_1 >> FMAN_IP_REV_1_MAJOR_SHIFT;
fman->ip_rev &= FMAN_IP_REV_1_MAJOR_MASK;
- DPAA_BUS_LOG(NOTICE, "FMan version is 0x%02x", fman->ip_rev);
+ DPAA_BUS_INFO("FMan version is 0x%02x", fman->ip_rev);
if (fman->ip_rev >= FMAN_V3) {
/*
@@ -795,8 +795,7 @@ fman_if_init(const struct device_node *dpa_node, int fd)
fman_if_vsp_init(__if);
/* Parsing of the network interface is complete, add it to the list */
- DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x,"
- "Port ID = %x",
+ DPAA_BUS_DEBUG("Found %s, Tx Channel = %x, FMAN = %x, Port ID = %x",
dname, __if->__if.tx_channel_id, __if->__if.fman->idx,
__if->__if.mac_idx);
@@ -1109,14 +1108,14 @@ fman_init(void)
fd = open(FMAN_DEVICE_PATH, O_RDWR);
if (unlikely(fd < 0)) {
- DPAA_BUS_LOG(ERR, "Unable to open %s: %s", FMAN_DEVICE_PATH, strerror(errno));
+ DPAA_BUS_ERR("Unable to open %s: %s", FMAN_DEVICE_PATH, strerror(errno));
return fd;
}
fman_ccsr_map_fd = fd;
parent_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa");
if (!parent_node) {
- DPAA_BUS_LOG(ERR, "Unable to find fsl,dpaa node");
+ DPAA_BUS_ERR("Unable to find fsl,dpaa node");
return -ENODEV;
}
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index ee467b94d5..b5bee268d6 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -560,12 +560,36 @@ rte_dpaa_bus_parse(const char *name, void *out)
static int
dpaa_bus_dev_compare(const char *name1, const char *name2)
{
+ int ret = 0;
char devname1[32], devname2[32];
if (rte_dpaa_bus_parse(name1, devname1) != 0 ||
rte_dpaa_bus_parse(name2, devname2) != 0)
return 1;
+#define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
+#define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
+ if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
+ (access(DPAA_DEV_PATH2, F_OK) != 0)) {
+ DPAA_BUS_DEBUG("DPAA Bus not present. Skipping.");
+ return 0;
+ }
+
+ if (dpaa_bus.detected)
+ return 0;
+
+ dpaa_bus.detected = 1;
+
+ /* create the key, supplying a function that'll be invoked
+ * when a portal affined thread will be deleted.
+ */
+ ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
+ if (ret) {
+ DPAA_BUS_DEBUG("Unable to create pthread key. (%d)", ret);
+ dpaa_clean_device_list();
+ return ret;
+ }
+
return strncmp(devname1, devname2, sizeof(devname1));
}
@@ -667,8 +691,6 @@ static int rte_dpaa_setup_intr(struct rte_intr_handle *intr_handle)
return 0;
}
-#define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
-#define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
static int
rte_dpaa_bus_scan(void)
@@ -715,12 +737,11 @@ rte_dpaa_bus_scan(void)
dpaa_bus.svr_ver = 0;
}
if (dpaa_bus.svr_ver == SVR_LS1046A_FAMILY) {
- DPAA_BUS_LOG(INFO, "This is LS1046A family SoC.");
+ DPAA_BUS_INFO("This is LS1046A family SoC.");
} else if (dpaa_bus.svr_ver == SVR_LS1043A_FAMILY) {
- DPAA_BUS_LOG(INFO, "This is LS1043A family SoC.");
+ DPAA_BUS_INFO("This is LS1043A family SoC.");
} else {
- DPAA_BUS_LOG(WARNING,
- "This is Unknown(%08x) DPAA1 family SoC.",
+ DPAA_BUS_WARN("This is Unknown(%08x) DPAA1 family SoC.",
dpaa_bus.svr_ver);
}
--
2.25.1
^ permalink raw reply related
* [PATCH v4 14/19] net/dpaa: optimize FMC MAC type parsing
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
For ls104xa, MAC9 and MAC10's type could be either of 10G/2.5G/1G
up to serdes configuration, MAC index should be identified by
port name instead of parsing MAC type and port number.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/net/dpaa/dpaa_fmc.c | 73 ++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 29 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_fmc.c b/drivers/net/dpaa/dpaa_fmc.c
index 7dc42f6e23..3034f534a5 100644
--- a/drivers/net/dpaa/dpaa_fmc.c
+++ b/drivers/net/dpaa/dpaa_fmc.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2017-2023 NXP
+ * Copyright 2017-2026 NXP
*/
/* System headers */
@@ -204,6 +204,36 @@ struct fmc_model_t {
struct fmc_model_t *g_fmc_model;
+static int
+dpaa_port_fmc_get_idx_from_name(const char *name)
+{
+ const char *found;
+ int idx_str_start = -1, idx;
+
+#define FMC_PORT_NAME_MAC "MAC/"
+#define FMC_PORT_NAME_OFFLINE "OFFLINE/"
+
+ found = strstr(name, FMC_PORT_NAME_MAC);
+ if (!found) {
+ found = strstr(name, FMC_PORT_NAME_OFFLINE);
+ if (found)
+ idx_str_start = strlen(FMC_PORT_NAME_OFFLINE);
+ } else {
+ idx_str_start = strlen(FMC_PORT_NAME_MAC);
+ }
+
+ if (!found) {
+ DPAA_PMD_ERR("Invalid fmc port name: %s", name);
+ return -EINVAL;
+ }
+
+ idx = atoi(&found[idx_str_start]);
+
+ DPAA_PMD_INFO("MAC index of %s is %d", name, idx);
+
+ return idx;
+}
+
static int
dpaa_port_fmc_port_parse(struct fman_if *fif,
const struct fmc_model_t *fmc_model,
@@ -211,7 +241,10 @@ dpaa_port_fmc_port_parse(struct fman_if *fif,
{
int current_port = fmc_model->apply_order[apply_idx].index;
const fmc_port *pport = &fmc_model->port[current_port];
- uint32_t num;
+ int num = dpaa_port_fmc_get_idx_from_name(pport->name);
+
+ if (num < 0)
+ return num;
if (pport->type == e_FM_PORT_TYPE_OH_OFFLINE_PARSING &&
pport->number == fif->mac_idx &&
@@ -219,40 +252,22 @@ dpaa_port_fmc_port_parse(struct fman_if *fif,
fif->mac_type == fman_onic))
return current_port;
- if (fif->mac_type == fman_mac_1g) {
- if (pport->type != e_FM_PORT_TYPE_RX)
- return -ENODEV;
- num = pport->number + DPAA_1G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
-
+ if (fif->mac_type == fman_mac_1g &&
+ pport->type != e_FM_PORT_TYPE_RX)
return -ENODEV;
- }
-
- if (fif->mac_type == fman_mac_2_5g) {
- if (pport->type != e_FM_PORT_TYPE_RX_2_5G)
- return -ENODEV;
- num = pport->number + DPAA_2_5G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
+ if (fif->mac_type == fman_mac_2_5g &&
+ pport->type != e_FM_PORT_TYPE_RX_2_5G)
return -ENODEV;
- }
-
- if (fif->mac_type == fman_mac_10g) {
- if (pport->type != e_FM_PORT_TYPE_RX_10G)
- return -ENODEV;
- num = pport->number + DPAA_10G_MAC_START_IDX;
- if (fif->mac_idx == num)
- return current_port;
+ if (fif->mac_type == fman_mac_10g &&
+ pport->type != e_FM_PORT_TYPE_RX_10G)
return -ENODEV;
- }
- DPAA_PMD_ERR("Invalid MAC(mac_idx=%d) type(%d)",
- fif->mac_idx, fif->mac_type);
+ if (fif->mac_idx == num)
+ return current_port;
- return -EINVAL;
+ return -ENODEV;
}
static int
--
2.25.1
^ permalink raw reply related
* [PATCH v4 15/19] net/dpaa: report error on using deferred start
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
This patch add support to report on error
for rx and tx deferred start config
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 2e3757ca03..83210ff775 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1174,6 +1174,12 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
rxq->nb_desc = UINT16_MAX;
rxq->offloads = rx_conf->offloads;
+ /* Rx deferred start is not supported */
+ if (rx_conf->rx_deferred_start) {
+ DPAA_PMD_ERR("%p:Rx deferred start not supported", (void *)dev);
+ return -EINVAL;
+ }
+
DPAA_PMD_INFO("Rx queue setup for queue index: %d fq_id (0x%x)",
queue_idx, rxq->fqid);
@@ -1480,6 +1486,12 @@ int dpaa_eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
txq->nb_desc = UINT16_MAX;
txq->offloads = tx_conf->offloads;
+ /* Tx deferred start is not supported */
+ if (tx_conf->tx_deferred_start) {
+ DPAA_PMD_ERR("%p:Tx deferred start not supported", (void *)dev);
+ return -EINVAL;
+ }
+
if (queue_idx >= dev->data->nb_tx_queues) {
rte_errno = EOVERFLOW;
DPAA_PMD_ERR("%p: queue index out of range (%u >= %u)",
--
2.25.1
^ permalink raw reply related
* [PATCH v4 16/19] drivers: optimize DPAA multi-entry buffer pool operations
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Replace the hardcoded buffer acquire count of 8 with the FSL_BM_BURST_MAX
constant when acquiring buffers from the buffer pool. Use a single
bm_hw_buf_desc structure for HW initialization of the first entry and copy
it to remaining entries, ensuring consistent HW descriptor state across
all entries in the pool.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 51 +++++++----------------------
drivers/bus/dpaa/include/fsl_bman.h | 46 +++++++++++++++++++++-----
drivers/mempool/dpaa/dpaa_mempool.c | 8 ++---
3 files changed, 54 insertions(+), 51 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index ee4232d0a0..01357d6446 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2016 Freescale Semiconductor Inc.
- * Copyright 2017, 2024 NXP
+ * Copyright 2017, 2024-2026 NXP
*
*/
#include <rte_memcpy.h>
@@ -17,20 +17,6 @@
#define IRQNAME "BMan portal %d"
#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */
-
-#define MAX_U16 UINT16_MAX
-#define MAX_U32 UINT32_MAX
-#ifndef BIT_SIZE
-#define BIT_SIZE(t) (sizeof(t) * 8)
-#endif
-#define MAX_U48 \
- ((((uint64_t)MAX_U16) << BIT_SIZE(uint32_t)) | MAX_U32)
-#define HI16_OF_U48(x) \
- (((x) >> BIT_SIZE(rte_be32_t)) & MAX_U16)
-#define LO32_OF_U48(x) ((x) & MAX_U32)
-#define U48_BY_HI16_LO32(hi, lo) \
- (((hi) << BIT_SIZE(uint32_t)) | (lo))
-
struct bman_portal {
struct bm_portal p;
/* 2-element array. pools[0] is mask, pools[1] is snapshot. */
@@ -273,7 +259,7 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
struct bm_rcr_entry *r;
uint8_t i, avail;
uint64_t bpid = pool->params.bpid;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -290,19 +276,17 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs,
if (unlikely(!r))
return -EBUSY;
+ bm_bufs[0].be_desc.bpid = bpid;
+ for (i = 0; i < num; i++)
+ bm_buffer_set64_to_be(&bm_bufs[i], bufs[i]);
/*
* we can copy all but the first entry, as this can trigger badness
* with the valid-bit
*/
- bm_bufs[0].bpid = bpid;
- bm_bufs[0].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[0]));
- bm_bufs[0].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[0]));
- for (i = 1; i < num; i++) {
- bm_bufs[i].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[i]));
- bm_bufs[i].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[i]));
- }
-
- memcpy(r->bufs, bm_bufs, sizeof(struct bm_buffer) * num);
+ r->bufs[0].opaque = bm_bufs[0].opaque;
+ if (num > 1)
+ rte_memcpy(&r->bufs[1], &bm_bufs[1],
+ sizeof(struct bm_buffer) * (num - 1));
bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE |
(num & BM_RCR_VERB_BUFCOUNT_MASK));
@@ -360,16 +344,6 @@ __rte_unused bman_extract_addr(struct bm_buffer *buf)
return buf->addr;
}
-static inline uint64_t
-bman_hw_extract_addr(struct bm_hw_buf_desc *buf)
-{
- uint64_t hi, lo;
-
- hi = be16_to_cpu(buf->hi_addr);
- lo = be32_to_cpu(buf->lo_addr);
- return U48_BY_HI16_LO32(hi, lo);
-}
-
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire_fast)
int
bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
@@ -378,7 +352,7 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
struct bm_mc_command *mcc;
struct bm_mc_result *mcr;
uint8_t i, rst;
- struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX];
+ struct bm_buffer bm_bufs[FSL_BM_BURST_MAX];
#ifdef RTE_LIBRTE_DPAA_HWDEBUG
if (!num || (num > FSL_BM_BURST_MAX))
@@ -397,11 +371,10 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num)
if (unlikely(rst < 1 || rst > FSL_BM_BURST_MAX))
return -EINVAL;
- rte_memcpy(bm_bufs, mcr->acquire.bufs,
- sizeof(struct bm_buffer) * rst);
+ rte_memcpy(bm_bufs, mcr->acquire.bufs, sizeof(struct bm_buffer) * rst);
for (i = 0; i < rst; i++)
- bufs[i] = bman_hw_extract_addr(&bm_bufs[i]);
+ bufs[i] = bm_buffer_get64_from_be(&bm_bufs[i]);
return rst;
}
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 2d24b89889..67a7a09618 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2024 NXP
+ * Copyright 2024-2026 NXP
*
*/
@@ -42,6 +42,13 @@ struct bm_mc_result; /* MC result */
* pool id specific to this buffer is needed (BM_RCR_VERB_CMD_BPID_MULTI,
* BM_MCC_VERB_ACQUIRE), the 'bpid' field is used.
*/
+struct __rte_packed_begin bm_hw_buf_desc {
+ uint8_t rsv;
+ uint8_t bpid;
+ rte_be16_t hi; /* High 16-bits of 48-bit address */
+ rte_be32_t lo; /* Low 32-bits of 48-bit address */
+} __rte_packed_end;
+
struct __rte_aligned(8) bm_buffer {
union {
struct {
@@ -66,17 +73,11 @@ struct __rte_aligned(8) bm_buffer {
u64 __notaddress:16;
#endif
};
+ struct bm_hw_buf_desc be_desc;
u64 opaque;
};
};
-struct __rte_packed_begin bm_hw_buf_desc {
- uint8_t rsv;
- uint8_t bpid;
- rte_be16_t hi_addr; /* High 16-bits of 48-bit address */
- rte_be32_t lo_addr; /* Low 32-bits of 48-bit address */
-} __rte_packed_end;
-
static inline u64 bm_buffer_get64(const struct bm_buffer *buf)
{
return buf->addr;
@@ -87,6 +88,17 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
return (dma_addr_t)buf->addr;
}
+#ifndef BIT_SIZE
+#define BIT_SIZE(t) (sizeof(t) * 8)
+#endif
+#define MAX_U48 \
+ ((((uint64_t)UINT16_MAX) << BIT_SIZE(uint32_t)) | UINT32_MAX)
+#define HI16_OF_U48(x) \
+ (((x) >> BIT_SIZE(uint32_t)) & UINT16_MAX)
+#define LO32_OF_U48(x) ((x) & UINT32_MAX)
+#define U48_BY_HI16_LO32(hi, lo) \
+ (((hi) << BIT_SIZE(uint32_t)) | (lo))
+
#define bm_buffer_set64(buf, v) \
do { \
struct bm_buffer *__buf931 = (buf); \
@@ -94,6 +106,24 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf)
__buf931->lo = lower_32_bits(v); \
} while (0)
+#define bm_buffer_set64_to_be(buf, v) \
+ do { \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ __buf931->be_desc.hi = cpu_to_be16(HI16_OF_U48(v)); \
+ __buf931->be_desc.lo = cpu_to_be32(LO32_OF_U48(v)); \
+ } while (0)
+
+#define bm_buffer_get64_from_be(buf) \
+ ({ \
+ uint64_t hi, lo; \
+ struct bm_buffer *__buf931 = (buf); \
+ \
+ hi = be16_to_cpu(__buf931->be_desc.hi); \
+ lo = be32_to_cpu(__buf931->be_desc.lo); \
+ U48_BY_HI16_LO32(hi, lo); \
+ })
+
#define FSL_BM_BURST_MAX 8
/* See 1.5.3.5.4: "Release Command" */
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 2f8555a026..3fdbcba646 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2023-2025 NXP
+ * Copyright 2017,2019,2023-2026 NXP
*
*/
@@ -50,7 +50,7 @@ static int
dpaa_mbuf_create_pool(struct rte_mempool *mp)
{
struct bman_pool *bp;
- struct bm_buffer bufs[8];
+ struct bm_buffer bufs[FSL_BM_BURST_MAX];
struct dpaa_bp_info *bp_info;
uint8_t bpid;
int num_bufs = 0, ret = 0;
@@ -83,8 +83,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
* then in 1s for the remainder.
*/
if (ret != 1)
- ret = bman_acquire(bp, bufs, 8, 0);
- if (ret < 8)
+ ret = bman_acquire(bp, bufs, FSL_BM_BURST_MAX, 0);
+ if (ret < FSL_BM_BURST_MAX)
ret = bman_acquire(bp, bufs, 1, 0);
if (ret > 0)
num_bufs += ret;
--
2.25.1
^ permalink raw reply related
* [PATCH v4 17/19] drivers: release DPAA bpid on driver destructor
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Track allocated BPIDs in a static per-BPID flag table and register a
driver destructor that releases any BPIDs still marked as in use at
process exit. This prevents BPID leaks when an application exits without
calling rte_mempool_free(). Also tune the per-lcore mempool cache flush
threshold to match the hardware bulk release size (DPAA_MBUF_MAX_ACQ_REL)
so that buffers are returned to HW in optimal burst sizes.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/qbman/bman.c | 8 +++
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fsl_bman.h | 3 ++
drivers/mempool/dpaa/dpaa_mempool.c | 67 ++++++++++++++++++++++--
drivers/mempool/dpaa/dpaa_mempool.h | 3 +-
5 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c
index 01357d6446..b69394b0cc 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -237,6 +237,14 @@ void bman_free_pool(struct bman_pool *pool)
kfree(pool);
}
+void bman_free_bpid(u8 bpid, u32 flags)
+{
+ if (flags & BMAN_POOL_FLAG_THRESH)
+ bm_pool_set(bpid, zero_thresholds);
+ if (flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ bman_release_bpid(bpid);
+}
+
const struct bman_pool_params *bman_get_params(const struct bman_pool *pool)
{
return &pool->params;
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 514ab7b1f1..8bd1a9bc6e 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -46,6 +46,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(netcfg_acquire)
RTE_EXPORT_INTERNAL_SYMBOL(netcfg_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_new_pool)
RTE_EXPORT_INTERNAL_SYMBOL(bman_free_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(bman_free_bpid)
RTE_EXPORT_INTERNAL_SYMBOL(bman_get_params)
RTE_EXPORT_INTERNAL_SYMBOL(bman_release)
RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire)
diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h
index 67a7a09618..6079eedff5 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -317,6 +317,9 @@ struct bman_pool *bman_new_pool(const struct bman_pool_params *params);
__rte_internal
void bman_free_pool(struct bman_pool *pool);
+__rte_internal
+void bman_free_bpid(u8 bpid, u32 flags);
+
/**
* bman_get_params - Returns a pool object's parameters.
* @pool: the pool object
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 3fdbcba646..210ea3bcf9 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -25,10 +25,22 @@
#include <rte_eal.h>
#include <rte_malloc.h>
#include <rte_ring.h>
+#include <rte_common.h>
#include <dpaa_mempool.h>
#include <dpaax_iova_table.h>
+struct dpaa_bpid_flag {
+ uint32_t flags;
+ int used;
+};
+
+/** Be referenced in destructor to release bpid allocated.
+ * Destructor can't access bman_pool from eal mem,
+ * we release ID with flag directly.
+ */
+static struct dpaa_bpid_flag s_dpaa_bpid_allocated_flag[DPAA_MAX_BPOOLS];
+
#define FMAN_ERRATA_BOUNDARY ((uint64_t)4096)
#define FMAN_ERRATA_BOUNDARY_MASK (~(FMAN_ERRATA_BOUNDARY - 1))
@@ -58,6 +70,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
struct bman_pool_params params = {
.flags = BMAN_POOL_FLAG_DYNAMIC_BPID
};
+ unsigned int lcore_id;
+ struct rte_mempool_cache *cache;
MEMPOOL_INIT_FUNC_TRACE();
@@ -115,7 +129,7 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_dpaa_bpid_info[bpid].ptov_off = 0;
rte_dpaa_bpid_info[bpid].flags = 0;
- bp_info = rte_malloc(NULL,
+ bp_info = rte_zmalloc(NULL,
sizeof(struct dpaa_bp_info),
RTE_CACHE_LINE_SIZE);
if (!bp_info) {
@@ -127,6 +141,20 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
sizeof(struct dpaa_bp_info));
mp->pool_data = (void *)bp_info;
+ s_dpaa_bpid_allocated_flag[bpid].flags = params.flags;
+ s_dpaa_bpid_allocated_flag[bpid].used = true;
+ /* Update per core mempool cache threshold to optimal value which is
+ * number of buffers that can be released to HW buffer pool in
+ * a single API call.
+ */
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ cache = &mp->local_cache[lcore_id];
+ DPAA_MEMPOOL_DEBUG("lCore %d: cache->flushthresh %d -> %d",
+ lcore_id, cache->flushthresh,
+ (uint32_t)(cache->size + DPAA_MBUF_MAX_ACQ_REL));
+ if (cache->flushthresh)
+ cache->flushthresh = cache->size + DPAA_MBUF_MAX_ACQ_REL;
+ }
DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
return 0;
@@ -136,6 +164,7 @@ static void
dpaa_mbuf_free_pool(struct rte_mempool *mp)
{
struct dpaa_bp_info *bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ uint16_t i;
MEMPOOL_INIT_FUNC_TRACE();
@@ -143,10 +172,25 @@ dpaa_mbuf_free_pool(struct rte_mempool *mp)
bman_free_pool(bp_info->bp);
DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
bp_info->bpid);
- rte_free(mp->pool_data);
- bp_info->bp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].mp = NULL;
+ rte_dpaa_bpid_info[bp_info->bpid].bp = NULL;
+ s_dpaa_bpid_allocated_flag[bp_info->bpid].used = false;
+ rte_free(bp_info);
mp->pool_data = NULL;
}
+
+ if (!rte_dpaa_bpid_info)
+ return;
+
+ for (i = 0; i < DPAA_MAX_BPOOLS; i++) {
+ if (rte_dpaa_bpid_info[i].mp)
+ break;
+ }
+
+ if (i == DPAA_MAX_BPOOLS) {
+ rte_free(rte_dpaa_bpid_info);
+ rte_dpaa_bpid_info = NULL;
+ }
}
static int
@@ -481,4 +525,21 @@ static const struct rte_mempool_ops dpaa_mpool_ops = {
.populate = dpaa_populate,
};
+#define RTE_PRIORITY_104 104
+
+RTE_FINI_PRIO(dpaa_mpool_finish, 104)
+{
+ uint16_t bpid;
+
+ for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
+ if (s_dpaa_bpid_allocated_flag[bpid].used) {
+ bman_free_bpid(bpid, s_dpaa_bpid_allocated_flag[bpid].flags);
+ s_dpaa_bpid_allocated_flag[bpid].used = false;
+ }
+ }
+ /** The rte_dpaa_bpid_info and bman_pool from EAL mem have been released
+ * with EAL mem pool being destroyed.
+ */
+}
+
RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/mempool/dpaa/dpaa_mempool.h b/drivers/mempool/dpaa/dpaa_mempool.h
index 865b533b8f..d7ee49b557 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.h
+++ b/drivers/mempool/dpaa/dpaa_mempool.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2019,2024 -2025 NXP
+ * Copyright 2017,2019,2024 -2026 NXP
*
*/
#ifndef __DPAA_MEMPOOL_H__
@@ -24,6 +24,7 @@
/* total number of bpools on SoC */
#define DPAA_MAX_BPOOLS 256
+#define DPAA_INVALID_BPID DPAA_MAX_BPOOLS
/* Maximum release/acquire from BMAN */
#define DPAA_MBUF_MAX_ACQ_REL FSL_BM_BURST_MAX
--
2.25.1
^ permalink raw reply related
* [PATCH v4 18/19] dma/dpaa: add SG data validation and ERR050757 fix
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Gagandeep Singh
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Gagandeep Singh <g.singh@nxp.com>
Add scatter-gather (SG) support to the QDMA driver, enabled by default
via the s_sg_enable flag. Add optional data validation mode controlled
by the s_data_validation flag for debugging transfer correctness.
Add a workaround for hardware errata ERR050757: when
RTE_DMA_DPAA_ERRATA_ERR050757 is defined, configure the source frame
descriptor with stride settings (sss/ssd = FSL_QDMA_CMD_SS_ERR050757_LEN)
to force PCI read transactions to stay within the errata-safe length
limit, preventing data corruption on affected silicon.
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
drivers/dma/dpaa/dpaa_qdma.c | 79 +++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 24 deletions(-)
diff --git a/drivers/dma/dpaa/dpaa_qdma.c b/drivers/dma/dpaa/dpaa_qdma.c
index af6083d2fe..d0d7998e5e 100644
--- a/drivers/dma/dpaa/dpaa_qdma.c
+++ b/drivers/dma/dpaa/dpaa_qdma.c
@@ -9,9 +9,14 @@
#include "dpaa_qdma.h"
#include "dpaa_qdma_logs.h"
+static int s_data_validation;
+static int s_hw_err_check;
+static int s_sg_enable = 1;
static uint32_t s_sg_max_entry_sz = 2000;
-static bool s_hw_err_check;
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+static int s_pci_read = 1;
+#endif
#define DPAA_DMA_ERROR_CHECK "dpaa_dma_err_check"
static inline void
@@ -112,7 +117,8 @@ dma_pool_alloc(char *nm, int size, int aligned, dma_addr_t *phy_addr)
if (!virt_addr)
return NULL;
- *phy_addr = rte_mem_virt2iova(virt_addr);
+ if (phy_addr)
+ *phy_addr = rte_mem_virt2iova(virt_addr);
return virt_addr;
}
@@ -392,6 +398,8 @@ fsl_qdma_data_validation(struct fsl_qdma_desc *desc[],
char err_msg[512];
int offset;
+ if (likely(!s_data_validation))
+ return;
offset = sprintf(err_msg, "Fatal TC%d/queue%d: ",
fsl_queue->block_id,
@@ -716,19 +724,21 @@ fsl_qdma_enqueue_desc_single(struct fsl_qdma_queue *fsl_queue,
ft = fsl_queue->ft[fsl_queue->ci];
#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
- sdf = &ft->df.sdf;
- sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
+ if (s_pci_read) {
+ sdf = &ft->df.sdf;
+ sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050265
- sdf->prefetch = 1;
+ sdf->prefetch = 1;
#endif
- if (len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
- sdf->ssen = 1;
- sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
- sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
- } else {
- sdf->ssen = 0;
- sdf->sss = 0;
- sdf->ssd = 0;
+ if (len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
+ sdf->ssen = 1;
+ sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ } else {
+ sdf->ssen = 0;
+ sdf->sss = 0;
+ sdf->ssd = 0;
+ }
}
#endif
csgf_src = &ft->desc_sbuf;
@@ -832,19 +842,21 @@ fsl_qdma_enqueue_desc_sg(struct fsl_qdma_queue *fsl_queue)
csgf_src->length = total_len;
csgf_dest->length = total_len;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
- sdf = &ft->df.sdf;
- sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
+ if (s_pci_read) {
+ sdf = &ft->df.sdf;
+ sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
#ifdef RTE_DMA_DPAA_ERRATA_ERR050265
- sdf->prefetch = 1;
+ sdf->prefetch = 1;
#endif
- if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
- sdf->ssen = 1;
- sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
- sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
- } else {
- sdf->ssen = 0;
- sdf->sss = 0;
- sdf->ssd = 0;
+ if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
+ sdf->ssen = 1;
+ sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
+ } else {
+ sdf->ssen = 0;
+ sdf->sss = 0;
+ sdf->ssd = 0;
+ }
}
#endif
ret = fsl_qdma_enqueue_desc_to_ring(fsl_queue, num);
@@ -883,6 +895,25 @@ fsl_qdma_enqueue_desc(struct fsl_qdma_queue *fsl_queue)
fsl_queue->pending_num = 0;
}
return ret;
+ } else if (!s_sg_enable) {
+ while (fsl_queue->pending_num > 0) {
+ ret = fsl_qdma_enqueue_desc_single(fsl_queue,
+ fsl_queue->pending_desc[start].dst,
+ fsl_queue->pending_desc[start].src,
+ fsl_queue->pending_desc[start].len);
+ if (!ret) {
+ start = (start + 1) &
+ (fsl_queue->pending_max - 1);
+ fsl_queue->pending_start = start;
+ fsl_queue->pending_num--;
+ } else {
+ DPAA_QDMA_ERR("Eq pending desc failed(%d)",
+ ret);
+ return -EIO;
+ }
+ }
+
+ return 0;
}
return fsl_qdma_enqueue_desc_sg(fsl_queue);
--
2.25.1
^ permalink raw reply related
* [PATCH v4 19/19] net/dpaa: add ONIC port checks
From: Hemant Agrawal @ 2026-06-21 17:27 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Vanshika Shukla
In-Reply-To: <20260621172731.2916346-1-hemant.agrawal@nxp.com>
From: Vanshika Shukla <vanshika.shukla@nxp.com>
Add fman_onic MAC type handling to get_rx_port_type() so that ONIC
and offline-internal ports are mapped to OH_OFFLINE_PARSING, consistent
with how the VSP port configuration handles these types. Without this,
ONIC ports used an incorrect port type in flow configuration, leading
to failed FMC operations.
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 26 ++++---
drivers/net/dpaa/dpaa_ethdev.h | 11 ++-
drivers/net/dpaa/dpaa_flow.c | 129 +++++++++++++++++----------------
drivers/net/dpaa/dpaa_flow.h | 7 +-
4 files changed, 93 insertions(+), 80 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 83210ff775..51ecf04c3c 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -490,7 +490,7 @@ static int dpaa_eth_dev_stop(struct rte_eth_dev *dev)
PMD_INIT_FUNC_TRACE();
dev->data->dev_started = 0;
- if (!fif->is_shared_mac) {
+ if (!fif->is_shared_mac && fif->mac_type != fman_onic) {
fman_if_bmi_stats_disable(fif);
fman_if_disable_rx(fif);
}
@@ -590,7 +590,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
}
}
if (fif->num_profiles) {
- ret = dpaa_port_vsp_cleanup(dpaa_intf, fif);
+ ret = dpaa_port_vsp_cleanup(dpaa_intf);
if (ret) {
DPAA_PMD_WARN("%s: cleanup VSP failed(%d)",
dev->data->name, ret);
@@ -676,7 +676,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev)
}
}
if (fif->num_profiles) {
- ret = dpaa_port_vsp_cleanup(dpaa_intf, fif);
+ ret = dpaa_port_vsp_cleanup(dpaa_intf);
if (ret) {
DPAA_PMD_WARN("%s: cleanup VSP failed(%d)",
dev->data->name, ret);
@@ -1136,8 +1136,8 @@ static inline int dpaa_eth_rx_queue_bp_check(struct rte_eth_dev *dev,
vsp_id = 0;
}
- if (dpaa_intf->vsp_bpid[vsp_id] &&
- bpid != dpaa_intf->vsp_bpid[vsp_id]) {
+ if (dpaa_intf->vsp[vsp_id].vsp_bp[0] &&
+ bpid != dpaa_intf->vsp[vsp_id].vsp_bp[0]->bpid) {
DPAA_PMD_ERR("Various MPs are assigned to RXQs with same VSP");
return -1;
@@ -1234,9 +1234,9 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
int8_t vsp_id = rxq->vsp_id;
if (vsp_id >= 0) {
- ret = dpaa_port_vsp_update(dpaa_intf, fmc_q, vsp_id,
- DPAA_MEMPOOL_TO_POOL_INFO(mp)->bpid,
- fif, buffsz + RTE_PKTMBUF_HEADROOM);
+ dpaa_intf->vsp[vsp_id].vsp_bp[0] = DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ dpaa_intf->vsp[vsp_id].bp_num = 1;
+ ret = dpaa_port_vsp_update(dpaa_intf, fmc_q, vsp_id, fif);
if (ret) {
DPAA_PMD_ERR("dpaa_port_vsp_update failed");
return ret;
@@ -1249,12 +1249,14 @@ int dpaa_eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
" to shared interface on DPDK.");
return -EINVAL;
}
- dpaa_intf->vsp_bpid[fif->base_profile_id] =
- DPAA_MEMPOOL_TO_POOL_INFO(mp)->bpid;
+ dpaa_intf->vsp[fif->base_profile_id].vsp_bp[0] =
+ DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ dpaa_intf->vsp[fif->base_profile_id].bp_num = 1;
}
} else {
- dpaa_intf->vsp_bpid[0] =
- DPAA_MEMPOOL_TO_POOL_INFO(mp)->bpid;
+ dpaa_intf->vsp[0].vsp_bp[0] =
+ DPAA_MEMPOOL_TO_POOL_INFO(mp);
+ dpaa_intf->vsp[0].bp_num = 1;
}
dpaa_intf->valid = 1;
diff --git a/drivers/net/dpaa/dpaa_ethdev.h b/drivers/net/dpaa/dpaa_ethdev.h
index d342d98f23..d3e005b556 100644
--- a/drivers/net/dpaa/dpaa_ethdev.h
+++ b/drivers/net/dpaa/dpaa_ethdev.h
@@ -118,6 +118,13 @@ enum {
#define FMC_FILE "/tmp/fmc.bin"
+struct dpaa_if_vsp {
+ struct dpaa_bp_info *vsp_bp[FMAN_PORT_MAX_EXT_POOLS_NUM];
+ uint8_t bp_num;
+ uint32_t max_size;
+ void *vsp_handle;
+};
+
extern struct rte_mempool *dpaa_tx_sg_pool;
/* PMD related logs */
@@ -164,8 +171,8 @@ struct dpaa_if {
*/
struct qman_fq *next_tx_conf_queue;
- void *vsp_handle[DPAA_VSP_PROFILE_MAX_NUM];
- uint32_t vsp_bpid[DPAA_VSP_PROFILE_MAX_NUM];
+ struct dpaa_if_vsp vsp[DPAA_VSP_PROFILE_MAX_NUM];
+ uint8_t base_vsp;
};
struct dpaa_if_stats {
diff --git a/drivers/net/dpaa/dpaa_flow.c b/drivers/net/dpaa/dpaa_flow.c
index 559850ced7..a10ca0cb56 100644
--- a/drivers/net/dpaa/dpaa_flow.c
+++ b/drivers/net/dpaa/dpaa_flow.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2017-2019,2021-2025 NXP
+ * Copyright 2017-2019,2021-2026 NXP
*/
/* System headers */
@@ -8,6 +8,7 @@
#include <unistd.h>
#include <sys/types.h>
+#include <dpaa_mempool.h>
#include <dpaa_ethdev.h>
#include <dpaa_flow.h>
#include <rte_dpaa_logs.h>
@@ -724,9 +725,6 @@ int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf,
PMD_INIT_FUNC_TRACE();
- if (!dpaa_intf->port_handle)
- return 0;
-
/* FM PORT Disable */
ret = fm_port_disable(dpaa_intf->port_handle);
if (ret != E_OK) {
@@ -786,8 +784,10 @@ int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
unsigned int i = 0;
PMD_INIT_FUNC_TRACE();
- if (dpaa_fm_deconfig(dpaa_intf, fif))
- DPAA_PMD_ERR("DPAA FM deconfig failed");
+ if (dpaa_intf->port_handle) {
+ if (dpaa_fm_deconfig(dpaa_intf, fif))
+ DPAA_PMD_ERR("DPAA FM deconfig failed");
+ }
if (!dev->data->nb_rx_queues)
return 0;
@@ -806,8 +806,7 @@ int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
if (fif->num_profiles) {
for (i = 0; i < dev->data->nb_rx_queues; i++)
- dpaa_intf->rx_queues[i].vsp_id =
- fm_default_vsp_id(fif);
+ dpaa_intf->rx_queues[i].vsp_id = fm_default_vsp_id(fif);
i = 0;
}
@@ -939,27 +938,16 @@ int dpaa_fm_term(void)
}
static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
- uint8_t vsp_id, t_handle fman_handle,
- struct fman_if *fif, u32 mbuf_data_room_size)
+ uint8_t vsp_id, t_handle fman_handle, struct fman_if *fif)
{
+ struct dpaa_if_vsp *vsp;
t_fm_vsp_params vsp_params;
t_fm_buffer_prefix_content buf_prefix_cont;
- uint8_t idx = mac_idx[fif->mac_idx];
+ uint8_t idx = mac_idx[fif->mac_idx], i;
int ret;
+ struct t_fm_ext_pools *pools;
- if (vsp_id == fif->base_profile_id && fif->is_shared_mac) {
- /* For shared interface, VSP of base
- * profile is default pool located in kernel.
- */
- dpaa_intf->vsp_bpid[vsp_id] = 0;
- return 0;
- }
-
- if (vsp_id >= DPAA_VSP_PROFILE_MAX_NUM) {
- DPAA_PMD_ERR("VSP ID %d exceeds MAX number %d",
- vsp_id, DPAA_VSP_PROFILE_MAX_NUM);
- return -1;
- }
+ vsp = &dpaa_intf->vsp[vsp_id];
memset(&vsp_params, 0, sizeof(vsp_params));
vsp_params.h_fm = fman_handle;
@@ -973,17 +961,21 @@ static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
vsp_params.port_params.port_type = get_rx_port_type(fif);
if (vsp_params.port_params.port_type == e_FM_PORT_TYPE_DUMMY) {
DPAA_PMD_ERR("Mac type %d error", fif->mac_type);
- return -1;
+ return -EINVAL;
}
- vsp_params.ext_buf_pools.num_of_pools_used = 1;
- vsp_params.ext_buf_pools.ext_buf_pool[0].id = dpaa_intf->vsp_bpid[vsp_id];
- vsp_params.ext_buf_pools.ext_buf_pool[0].size = mbuf_data_room_size;
+ pools = &vsp_params.ext_buf_pools;
- dpaa_intf->vsp_handle[vsp_id] = fm_vsp_config(&vsp_params);
- if (!dpaa_intf->vsp_handle[vsp_id]) {
- DPAA_PMD_ERR("fm_vsp_config error for profile %d", vsp_id);
- return -EINVAL;
+ pools->num_of_pools_used = vsp->bp_num;
+ for (i = 0; i < vsp->bp_num; i++) {
+ pools->ext_buf_pool[i].id = vsp->vsp_bp[i]->bpid;
+ pools->ext_buf_pool[i].size = vsp->vsp_bp[i]->size;
+ }
+
+ vsp->vsp_handle = fm_vsp_config(&vsp_params);
+ if (!vsp->vsp_handle) {
+ DPAA_PMD_ERR("Configure VSP[%d] failed!", vsp_id);
+ return -EIO;
}
/* configure the application buffer (structure, size and
@@ -1001,19 +993,18 @@ static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
buf_prefix_cont.manip_ext_space =
RTE_PKTMBUF_HEADROOM - DPAA_MBUF_HW_ANNOTATION;
- ret = fm_vsp_config_buffer_prefix_content(dpaa_intf->vsp_handle[vsp_id],
- &buf_prefix_cont);
+ ret = fm_vsp_config_buffer_prefix_content(vsp->vsp_handle,
+ &buf_prefix_cont);
if (ret != E_OK) {
- DPAA_PMD_ERR("fm_vsp_config_buffer_prefix_content error for profile %d err: %d",
- vsp_id, ret);
+ DPAA_PMD_ERR("Configure VSP[%d]'s buffer prefix failed(%d)!",
+ vsp_id, ret);
return ret;
}
/* initialize the FM VSP module */
- ret = fm_vsp_init(dpaa_intf->vsp_handle[vsp_id]);
+ ret = fm_vsp_init(vsp->vsp_handle);
if (ret != E_OK) {
- DPAA_PMD_ERR("fm_vsp_init error for profile %d err:%d",
- vsp_id, ret);
+ DPAA_PMD_ERR("Init VSP[%d] failed(%d)!", vsp_id, ret);
return ret;
}
@@ -1021,29 +1012,44 @@ static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
}
int dpaa_port_vsp_update(struct dpaa_if *dpaa_intf,
- bool fmc_mode, uint8_t vsp_id, uint32_t bpid,
- struct fman_if *fif, u32 mbuf_data_room_size)
+ bool fmc_mode, uint8_t vsp_id, struct fman_if *fif)
{
int ret = 0;
t_handle fman_handle;
+ struct dpaa_if_vsp *vsp;
- if (!fif->num_profiles)
- return 0;
+ if (!fif->num_profiles) {
+ DPAA_PMD_ERR("%s: No multiple VSPs specified!",
+ dpaa_intf->name);
+ return -EINVAL;
+ }
- if (vsp_id >= fif->num_profiles)
- return 0;
+ if (vsp_id >= (fif->base_profile_id + fif->num_profiles)) {
+ DPAA_PMD_ERR("%s: Invalid VSP ID(%d) >= base(%d) + num(%d)",
+ dpaa_intf->name, vsp_id, fif->base_profile_id,
+ fif->num_profiles);
+ return -EINVAL;
+ }
- if (dpaa_intf->vsp_bpid[vsp_id] == bpid)
+ if (vsp_id == fif->base_profile_id && fif->is_shared_mac) {
+ /* For shared interface, VSP of base
+ * profile is default pool located in kernel.
+ */
+ dpaa_intf->vsp[vsp_id].bp_num = 0;
+ dpaa_intf->vsp[vsp_id].vsp_handle = NULL;
return 0;
+ }
+
+ vsp = &dpaa_intf->vsp[vsp_id];
- if (dpaa_intf->vsp_handle[vsp_id]) {
- ret = fm_vsp_free(dpaa_intf->vsp_handle[vsp_id]);
+ if (vsp->vsp_handle) {
+ ret = fm_vsp_free(vsp->vsp_handle);
if (ret != E_OK) {
- DPAA_PMD_ERR("Error fm_vsp_free: err %d vsp_handle[%d]",
- ret, vsp_id);
+ DPAA_PMD_ERR("Free VSP[%d]'s handle failed(%d)",
+ vsp_id, ret);
return ret;
}
- dpaa_intf->vsp_handle[vsp_id] = 0;
+ vsp->vsp_handle = NULL;
}
if (fmc_mode)
@@ -1051,24 +1057,23 @@ int dpaa_port_vsp_update(struct dpaa_if *dpaa_intf,
else
fman_handle = fm_info.fman_handle;
- dpaa_intf->vsp_bpid[vsp_id] = bpid;
-
- return dpaa_port_vsp_configure(dpaa_intf, vsp_id, fman_handle, fif,
- mbuf_data_room_size);
+ return dpaa_port_vsp_configure(dpaa_intf, vsp_id, fman_handle, fif);
}
-int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf, struct fman_if *fif)
+int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf)
{
- int idx, ret;
+ int ret;
+ uint8_t idx;
- for (idx = 0; idx < (uint8_t)fif->num_profiles; idx++) {
- if (dpaa_intf->vsp_handle[idx]) {
- ret = fm_vsp_free(dpaa_intf->vsp_handle[idx]);
+ for (idx = 0; idx < DPAA_VSP_PROFILE_MAX_NUM; idx++) {
+ if (dpaa_intf->vsp[idx].vsp_handle) {
+ ret = fm_vsp_free(dpaa_intf->vsp[idx].vsp_handle);
if (ret != E_OK) {
- DPAA_PMD_ERR("Error fm_vsp_free: err %d"
- " vsp_handle[%d]", ret, idx);
+ DPAA_PMD_ERR("Free VSP[%d] failed(%d)",
+ idx, ret);
return ret;
}
+ dpaa_intf->vsp[idx].vsp_handle = NULL;
}
}
diff --git a/drivers/net/dpaa/dpaa_flow.h b/drivers/net/dpaa/dpaa_flow.h
index 4742b8dd0a..6a949d6dd4 100644
--- a/drivers/net/dpaa/dpaa_flow.h
+++ b/drivers/net/dpaa/dpaa_flow.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2017,2019,2022 NXP
+ * Copyright 2017,2019,2022,2026 NXP
*/
#ifndef __DPAA_FLOW_H__
@@ -11,9 +11,8 @@ int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set);
int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf, struct fman_if *fif);
void dpaa_write_fm_config_to_file(void);
int dpaa_port_vsp_update(struct dpaa_if *dpaa_intf,
- bool fmc_mode, uint8_t vsp_id, uint32_t bpid, struct fman_if *fif,
- u32 mbuf_data_room_size);
-int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf, struct fman_if *fif);
+ bool fmc_mode, uint8_t vsp_id, struct fman_if *fif);
+int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf);
int dpaa_port_fmc_init(struct fman_if *fif,
uint32_t *fqids, int8_t *vspids, int max_nb_rxq);
--
2.25.1
^ permalink raw reply related
* [PATCH v4] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-21 17:55 UTC (permalink / raw)
To: dev, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
Cc: Morten Brørup
In-Reply-To: <20260619202047.2809165-1-mb@smartsharesystems.com>
Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v4:
* Added documentation. (AI)
* Added more comments. (AI)
* Improved dump. (AI)
v3:
* Debug shows cycles/obj instead of cycles/call.
* Fixed missing --in-reply-to.
v2:
* Fixed indentation.
---
config/rte_config.h | 1 +
doc/guides/prog_guide/graph_lib.rst | 1 +
lib/graph/graph_debug.c | 39 ++++++++++++++++++++++++++++-
lib/graph/node.c | 2 ++
lib/graph/rte_graph_worker_common.h | 23 ++++++++++++++---
5 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
/* rte_graph defines */
#define RTE_GRAPH_BURST_SIZE 256
#define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
/****** driver defines ********/
diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst
index 8dd49c19d2..bc36042296 100644
--- a/doc/guides/prog_guide/graph_lib.rst
+++ b/doc/guides/prog_guide/graph_lib.rst
@@ -49,6 +49,7 @@ Performance tuning parameters
RTE_GRAPH_BURST_SIZE config option.
The testing shows, on x86 and arm64 servers, The sweet spot is 256 burst
size. While on arm64 embedded SoCs, it is either 64 or 128.
+- Enable the ``RTE_GRAPH_PROFILE`` config option for more profiling details.
- Disable node statistics (using ``RTE_LIBRTE_GRAPH_STATS`` config option)
if not needed.
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..2aa1e4d22f 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -92,7 +92,44 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
fprintf(f, " total_sched_fail=%" PRId64 "\n",
n->dispatch.total_sched_fail);
}
- fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
+ fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
+ if (rte_graph_has_stats_feature()) {
+ fprintf(f, " total_cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ n->total_cycles,
+ n->total_calls == 0 ? (double)0 :
+ (double)n->total_cycles / (double)n->total_calls);
+ }
+#ifdef RTE_GRAPH_PROFILE
+ uint64_t calls = n->usage_stats[0].calls;
+ fprintf(f, " objs[0]\n");
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ calls,
+ n->usage_stats[0].cycles,
+ calls == 0 ? 0.0 :
+ (double)n->usage_stats[0].cycles / (double)calls);
+ calls = n->usage_stats[1].calls;
+ fprintf(f, " objs[1]\n");
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ calls,
+ n->usage_stats[1].cycles,
+ calls == 0 ? 0.0 :
+ (double)n->usage_stats[1].cycles / (double)calls);
+ calls = RTE_MAX(INT64_C(0), (int64_t)(n->total_calls -
+ (n->usage_stats[0].calls + n->usage_stats[1].calls)));
+ uint64_t cycles = RTE_MAX(INT64_C(0), (int64_t)(n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles)));
+ uint64_t objs = RTE_MAX(INT64_C(0), (int64_t)(n->total_objs -
+ n->usage_stats[1].calls));
+ double objs_per_call = calls == 0 ? 0.0 : (double)objs / (double)calls;
+ fprintf(f, " objs[more], avg objs/call=%.1f\n", objs_per_call);
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f"
+ ", avg cycles/obj=%.1f\n",
+ calls,
+ cycles,
+ calls == 0 ? 0.0 : (double)cycles / (double)calls,
+ calls == 0 || objs_per_call == 0.0 ? 0.0 :
+ (double)cycles / (double)calls / objs_per_call);
+#endif
for (i = 0; i < n->nb_edges; i++)
fprintf(f, " edge[%d] <%s>\n", i,
n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
rte_edge_t i;
size_t sz;
+#ifndef RTE_GRAPH_PROFILE
/* Limit Node specific metadata to one cacheline on 64B CL machine */
RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
offsetof(struct rte_node, ctx)) !=
RTE_CACHE_LINE_MIN_SIZE);
+#endif
graph_spinlock_lock();
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..10a52a540b 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -144,12 +144,22 @@ struct __rte_cache_aligned rte_node {
rte_node_process_t process; /**< Process function. */
uint64_t process_u64;
};
+ /** Fast path area cache line 3. */
+#ifdef RTE_GRAPH_PROFILE
+ struct {
+ uint64_t calls; /**< Calls processing resp. 0 or 1 objects. */
+ uint64_t cycles; /**< Cycles spent processing resp. 0 or 1 objects. */
+ } usage_stats[2]; /**< Usage when this node processed 0 or 1 objects. */
+ /** Fast path area cache line 4. */
+#endif
alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[]; /**< Next nodes. */
};
};
+#ifndef RTE_GRAPH_PROFILE
static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
/**
* @internal
@@ -197,7 +207,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
static __rte_always_inline void
__rte_node_process(struct rte_graph *graph, struct rte_node *node)
{
- uint64_t start;
+ uint64_t cycles;
uint16_t rc;
void **objs;
@@ -206,11 +216,18 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
rte_prefetch0(objs);
if (rte_graph_has_stats_feature()) {
- start = rte_rdtsc();
+ cycles = -rte_rdtsc();
rc = node->process(graph, node, objs, node->idx);
- node->total_cycles += rte_rdtsc() - start;
+ cycles += rte_rdtsc();
+ node->total_cycles += cycles;
node->total_calls++;
node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+ if (rc <= 1) {
+ node->usage_stats[rc].calls++;
+ node->usage_stats[rc].cycles += cycles;
+ }
+#endif
} else {
node->process(graph, node, objs, node->idx);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v5] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-21 18:41 UTC (permalink / raw)
To: dev, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
Cc: Morten Brørup
In-Reply-To: <20260619202047.2809165-1-mb@smartsharesystems.com>
Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v5:
* Added stats for a half burst and a full burst.
v4:
* Added documentation. (AI)
* Added more comments. (AI)
* Improved dump. (AI)
* Debug shows both cycles/call and cycles/obj.
v3:
* Debug shows cycles/obj instead of cycles/call.
* Fixed missing --in-reply-to.
v2:
* Fixed indentation.
---
config/rte_config.h | 1 +
doc/guides/prog_guide/graph_lib.rst | 1 +
lib/graph/graph_debug.c | 57 ++++++++++++++++++++++++++++-
lib/graph/node.c | 2 +
lib/graph/rte_graph_worker_common.h | 33 +++++++++++++++--
5 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
/* rte_graph defines */
#define RTE_GRAPH_BURST_SIZE 256
#define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
/****** driver defines ********/
diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst
index 8dd49c19d2..bc36042296 100644
--- a/doc/guides/prog_guide/graph_lib.rst
+++ b/doc/guides/prog_guide/graph_lib.rst
@@ -49,6 +49,7 @@ Performance tuning parameters
RTE_GRAPH_BURST_SIZE config option.
The testing shows, on x86 and arm64 servers, The sweet spot is 256 burst
size. While on arm64 embedded SoCs, it is either 64 or 128.
+- Enable the ``RTE_GRAPH_PROFILE`` config option for more profiling details.
- Disable node statistics (using ``RTE_LIBRTE_GRAPH_STATS`` config option)
if not needed.
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..7c97e23748 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -92,7 +92,62 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
fprintf(f, " total_sched_fail=%" PRId64 "\n",
n->dispatch.total_sched_fail);
}
- fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
+ fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
+ if (rte_graph_has_stats_feature()) {
+ fprintf(f, " total_cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ n->total_cycles,
+ n->total_calls == 0 ? (double)0 :
+ (double)n->total_cycles / (double)n->total_calls);
+ }
+#ifdef RTE_GRAPH_PROFILE
+ uint64_t calls = n->usage_stats[0].calls;
+ fprintf(f, " objs[0]\n");
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ calls,
+ n->usage_stats[0].cycles,
+ calls == 0 ? 0.0 :
+ (double)n->usage_stats[0].cycles / (double)calls);
+ calls = n->usage_stats[1].calls;
+ fprintf(f, " objs[1]\n");
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+ calls,
+ n->usage_stats[1].cycles,
+ calls == 0 ? 0.0 :
+ (double)n->usage_stats[1].cycles / (double)calls);
+ calls = RTE_MAX(INT64_C(0), (int64_t)(n->total_calls -
+ (n->usage_stats[0].calls + n->usage_stats[1].calls)));
+ uint64_t cycles = RTE_MAX(INT64_C(0), (int64_t)(n->total_cycles -
+ (n->usage_stats[0].cycles + n->usage_stats[1].cycles)));
+ uint64_t objs = RTE_MAX(INT64_C(0), (int64_t)(n->total_objs -
+ n->usage_stats[1].calls));
+ double objs_per_call = calls == 0 ? 0.0 : (double)objs / (double)calls;
+ fprintf(f, " objs[more], avg objs/call=%.1f\n", objs_per_call);
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f"
+ ", avg cycles/obj=%.1f\n",
+ calls,
+ cycles,
+ calls == 0 ? 0.0 : (double)cycles / (double)calls,
+ calls == 0 || objs_per_call == 0.0 ? 0.0 :
+ (double)cycles / (double)calls / objs_per_call);
+ calls = n->half_burst_calls;
+ fprintf(f, " objs[%u]\n", RTE_GRAPH_BURST_SIZE / 2);
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f"
+ ", avg cycles/obj=%.1f\n",
+ calls,
+ n->half_burst_cycles,
+ calls == 0 ? 0.0 : (double)n->half_burst_cycles / (double)calls,
+ calls == 0 ? 0.0 : (double)n->half_burst_cycles / (double)calls /
+ (double)(RTE_GRAPH_BURST_SIZE / 2));
+ calls = n->full_burst_calls;
+ fprintf(f, " objs[%u]\n", RTE_GRAPH_BURST_SIZE);
+ fprintf(f, " calls=%" PRIu64 ", cycles=%" PRIu64 ", avg cycles/call=%.1f"
+ ", avg cycles/obj=%.1f\n",
+ calls,
+ n->full_burst_cycles,
+ calls == 0 ? 0.0 : (double)n->full_burst_cycles / (double)calls,
+ calls == 0 ? 0.0 : (double)n->full_burst_cycles / (double)calls /
+ (double)RTE_GRAPH_BURST_SIZE);
+#endif
for (i = 0; i < n->nb_edges; i++)
fprintf(f, " edge[%d] <%s>\n", i,
n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
rte_edge_t i;
size_t sz;
+#ifndef RTE_GRAPH_PROFILE
/* Limit Node specific metadata to one cacheline on 64B CL machine */
RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
offsetof(struct rte_node, ctx)) !=
RTE_CACHE_LINE_MIN_SIZE);
+#endif
graph_spinlock_lock();
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..0d8039575d 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -144,12 +144,26 @@ struct __rte_cache_aligned rte_node {
rte_node_process_t process; /**< Process function. */
uint64_t process_u64;
};
+ /** Fast path area cache line 3. */
+#ifdef RTE_GRAPH_PROFILE
+ struct {
+ uint64_t calls; /**< Calls processing resp. 0 or 1 objects. */
+ uint64_t cycles; /**< Cycles spent processing resp. 0 or 1 objects. */
+ } usage_stats[2]; /**< Usage when this node processed 0 or 1 objects. */
+ uint64_t full_burst_calls; /**< Calls processing a full burst of objects. */
+ uint64_t full_burst_cycles; /**< Cycles spent processing a full burst of objects. */
+ uint64_t half_burst_calls; /**< Calls processing a half burst of objects. */
+ uint64_t half_burst_cycles; /**< Cycles spent processing a half burst of objects. */
+ /** Fast path area cache line 4. */
+#endif
alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[]; /**< Next nodes. */
};
};
+#ifndef RTE_GRAPH_PROFILE
static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
/**
* @internal
@@ -197,7 +211,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
static __rte_always_inline void
__rte_node_process(struct rte_graph *graph, struct rte_node *node)
{
- uint64_t start;
+ uint64_t cycles;
uint16_t rc;
void **objs;
@@ -206,11 +220,24 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
rte_prefetch0(objs);
if (rte_graph_has_stats_feature()) {
- start = rte_rdtsc();
+ cycles = -rte_rdtsc();
rc = node->process(graph, node, objs, node->idx);
- node->total_cycles += rte_rdtsc() - start;
+ cycles += rte_rdtsc();
+ node->total_cycles += cycles;
node->total_calls++;
node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+ if (rc <= 1) {
+ node->usage_stats[rc].calls++;
+ node->usage_stats[rc].cycles += cycles;
+ } else if (rc == RTE_GRAPH_BURST_SIZE) {
+ node->full_burst_calls++;
+ node->full_burst_cycles += cycles;
+ } else if (rc == RTE_GRAPH_BURST_SIZE / 2) {
+ node->half_burst_calls++;
+ node->half_burst_cycles += cycles;
+ }
+#endif
} else {
node->process(graph, node, objs, node->idx);
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v1 0/5] prefix lcore role enum values
From: lihuisong (C) @ 2026-06-22 1:22 UTC (permalink / raw)
To: Stephen Hemminger, Morten Brørup, thomas
Cc: andrew.rybchenko, dev, zhanjie9
In-Reply-To: <20260618190339.2fc76616@phoenix.local>
On 6/19/2026 10:03 AM, Stephen Hemminger wrote:
> On Wed, 17 Jun 2026 13:48:37 +0200
> Morten Brørup <mb@smartsharesystems.com> wrote:
>
>>> From: Huisong Li [mailto:lihuisong@huawei.com]
>>> Sent: Wednesday, 17 June 2026 12.28
>>>
>>> Add the RTE_LCORE_ prefix to the lcore role enum values in
>>> rte_lcore_role_t
>>> to follow DPDK naming conventions.
>>>
>>> - ROLE_RTE -> RTE_LCORE_ROLE_RTE
>>> - ROLE_OFF -> RTE_LCORE_ROLE_OFF
>>> - ROLE_SERVICE -> RTE_LCORE_ROLE_SERVICE
>>> - ROLE_NON_EAL -> RTE_LCORE_ROLE_NON_EAL
>>>
>>> Old names are kept as macros aliasing to the new names to preserve
>>> backward compatibility.
>>>
>> Series-Acked-by: Morten Brørup <mb@smartsharesystems.com>
>>
> The problem with this patch it causes build failures now with abi diff.
>
> Example build log...
>
>
> 2 functions with some indirect sub-type change:
>
>
>
>
>
> [C] 'function rte_lcore_role_t rte_eal_lcore_role(unsigned int)' at eal_common_lcore.c:74:1 has some indirect sub-type changes:
>
> return type changed:
>
> type size hasn't changed
>
> 4 enumerator deletions:
>
> 'rte_lcore_role_t::ROLE_RTE' value '0'
>
> 'rte_lcore_role_t::ROLE_OFF' value '1'
>
> 'rte_lcore_role_t::ROLE_SERVICE' value '2'
>
> 'rte_lcore_role_t::ROLE_NON_EAL' value '3'
>
> 4 enumerator insertions:
>
> 'rte_lcore_role_t::RTE_LCORE_ROLE_RTE' value '0'
>
> 'rte_lcore_role_t::RTE_LCORE_ROLE_OFF' value '1'
>
> 'rte_lcore_role_t::RTE_LCORE_ROLE_SERVICE' value '2'
>
> 'rte_lcore_role_t::RTE_LCORE_ROLE_NON_EAL' value '3'
>
>
>
>
>
> [C] 'function int rte_lcore_has_role(unsigned int, rte_lcore_role_t)' at eal_common_lcore.c:85:1 has some indirect sub-type changes:
>
> parameter 2 of type 'enum rte_lcore_role_t' has sub-type changes:
>
> enum type 'enum rte_lcore_role_t' changed at rte_lcore.h:33:1, as reported earlier
>
>
>
>
>
>
>
> Error: ABI issue reported for abidiff --suppr /home/runner/work/dpdk/dpdk/devtools/libabigail.abignore --no-added-syms --headers-dir1 reference/usr/local/include --headers-dir2 install/usr/local/include reference/usr/local/lib/librte_eal.so.26.1 install/usr/local/lib/librte_eal.so.26.2
We just came back from the Dragon Boat Festival.
I also received this ABI change warning. But I didn't have any good
ideas yet.
Thanks for helping to handle this.
Sorry for the inconvenience.
^ permalink raw reply
* [PATCH 0/2] test/dma: improve dmadev tests
From: Tejasree Kondoj @ 2026-06-22 3:06 UTC (permalink / raw)
To: Akhil Goyal, Chengwen Feng, Kevin Laatz, Bruce Richardson
Cc: Vidya Sagar Velumuri, Anoob Joseph, dev
Extend dmadev tests for SG wrap-around and zero/one fill coverage.
Tejasree Kondoj (2):
test/dma: update the sg test to verify wrap around case
test/dma: add functions to verify zero and one fill
app/test/test.h | 4 ++
app/test/test_dmadev.c | 102 +++++++++++++++++------------
app/test/test_dmadev_api.c | 1 -
app/test/test_dmadev_api.h | 2 ++
4 files changed, 72 insertions(+), 25 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH 1/2] test/dma: update the sg test to verify wrap around case
From: Tejasree Kondoj @ 2026-06-22 3:06 UTC (permalink / raw)
To: Akhil Goyal, Chengwen Feng, Kevin Laatz, Bruce Richardson
Cc: Vidya Sagar Velumuri, Anoob Joseph, dev
In-Reply-To: <20260622030623.86094-1-ktejasree@marvell.com>
Run the sg test in a loop to verify wrap around case.
Total number commands submitted to be more than the number descriptors
allocated to verify the scenario.
Signed-off-by: Vidya Sagar Velumuri <vvelumuri@marvell.com>
---
app/test/test_dmadev.c | 45 ++++++++++++++++++++++++--------------
app/test/test_dmadev_api.c | 1 -
app/test/test_dmadev_api.h | 2 ++
3 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/app/test/test_dmadev.c b/app/test/test_dmadev.c
index 5488a1af33..b30f2214e5 100644
--- a/app/test/test_dmadev.c
+++ b/app/test/test_dmadev.c
@@ -393,36 +393,28 @@ test_stop_start(int16_t dev_id, uint16_t vchan)
}
static int
-test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
+test_enqueue_sg(int16_t dev_id, uint16_t vchan, unsigned int n_sge, unsigned int test_len)
{
- unsigned int src_len, dst_len, n_sge, len, i, j, k;
char orig_src[COPY_LEN], orig_dst[COPY_LEN];
- struct rte_dma_info info = { 0 };
+ unsigned int src_len, dst_len, i, j, k;
enum rte_dma_status_code status;
uint16_t id, n_src, n_dst;
- if (rte_dma_info_get(dev_id, &info) < 0)
- ERR_RETURN("Failed to get dev info");
-
- if (info.max_sges < 2)
- ERR_RETURN("Test needs minimum 2 SG pointers");
-
- n_sge = info.max_sges;
-
for (n_src = 1; n_src <= n_sge; n_src++) {
for (n_dst = 1; n_dst <= n_sge; n_dst++) {
/* Normalize SG buffer lengths */
- len = COPY_LEN;
- len -= (len % (n_src * n_dst));
- dst_len = len / n_dst;
- src_len = len / n_src;
-
struct rte_dma_sge *sg_src = alloca(sizeof(struct rte_dma_sge) * n_sge);
struct rte_dma_sge *sg_dst = alloca(sizeof(struct rte_dma_sge) * n_sge);
struct rte_mbuf **src = alloca(sizeof(struct rte_mbuf *) * n_sge);
struct rte_mbuf **dst = alloca(sizeof(struct rte_mbuf *) * n_sge);
char **src_data = alloca(sizeof(char *) * n_sge);
char **dst_data = alloca(sizeof(char *) * n_sge);
+ unsigned int len = test_len - (test_len % (n_src * n_dst));
+
+ dst_len = len / n_dst;
+ src_len = len / n_src;
+ if (dst_len == 0 || src_len == 0)
+ continue;
for (i = 0 ; i < len; i++)
orig_src[i] = rte_rand() & 0xFF;
@@ -514,6 +506,27 @@ test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
return 0;
}
+static int
+test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
+{
+ struct rte_dma_info info = { 0 };
+ unsigned int n_sge, len;
+ int loop_count = 0;
+
+ if (rte_dma_info_get(dev_id, &info) < 0)
+ ERR_RETURN("Failed to get dev info");
+
+ n_sge = RTE_MIN(info.max_sges, TEST_SG_MAX);
+ len = COPY_LEN;
+
+ do {
+ test_enqueue_sg(dev_id, vchan, n_sge, len);
+ loop_count++;
+ } while (loop_count * n_sge * n_sge < TEST_RINGSIZE * 3);
+
+ return 0;
+}
+
static int
test_single_sva_copy(int16_t dev_id, uint16_t vchan, const char *mem_src,
char *src, char *dst, uint32_t len)
diff --git a/app/test/test_dmadev_api.c b/app/test/test_dmadev_api.c
index 1ba053696b..4bb8f9e820 100644
--- a/app/test/test_dmadev_api.c
+++ b/app/test/test_dmadev_api.c
@@ -16,7 +16,6 @@ extern int test_dma_api(uint16_t dev_id);
#define TEST_MEMCPY_SIZE 1024
#define TEST_WAIT_US_VAL 50000
-#define TEST_SG_MAX 64
static int16_t test_dev_id;
static int16_t invalid_dev_id;
diff --git a/app/test/test_dmadev_api.h b/app/test/test_dmadev_api.h
index 33fbc5bd41..a03f7acd4f 100644
--- a/app/test/test_dmadev_api.h
+++ b/app/test/test_dmadev_api.h
@@ -2,4 +2,6 @@
* Copyright(c) 2021 HiSilicon Limited
*/
+#define TEST_SG_MAX 64
+
int test_dma_api(uint16_t dev_id);
--
2.34.1
^ permalink raw reply related
* [PATCH 2/2] test/dma: add functions to verify zero and one fill
From: Tejasree Kondoj @ 2026-06-22 3:06 UTC (permalink / raw)
To: Akhil Goyal, Chengwen Feng, Kevin Laatz, Bruce Richardson
Cc: Vidya Sagar Velumuri, Anoob Joseph, dev
In-Reply-To: <20260622030623.86094-1-ktejasree@marvell.com>
Add test cases to verify zero fill and one fill
Signed-off-by: Vidya Sagar Velumuri <vvelumuri@marvell.com>
---
app/test/test.h | 4 +++
app/test/test_dmadev.c | 57 ++++++++++++++++++++++++------------------
2 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/app/test/test.h b/app/test/test.h
index 1f12fc5397..5fc2d7d048 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -28,6 +28,10 @@
#include <rte_test.h>
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
#define TEST_ASSERT RTE_TEST_ASSERT
#define TEST_ASSERT_EQUAL RTE_TEST_ASSERT_EQUAL
diff --git a/app/test/test_dmadev.c b/app/test/test_dmadev.c
index b30f2214e5..d4299e501d 100644
--- a/app/test/test_dmadev.c
+++ b/app/test/test_dmadev.c
@@ -931,42 +931,51 @@ test_completion_handling(int16_t dev_id, uint16_t vchan)
static int
test_enqueue_fill(int16_t dev_id, uint16_t vchan)
{
+ uint64_t pattern[3] = {0x0, 0xfedcba9876543210, 0xffffffffffffffff};
const unsigned int lengths[] = {8, 64, 1024, 50, 100, 89};
+ unsigned int i, j, k;
struct rte_mbuf *dst;
char *dst_data;
- uint64_t pattern = 0xfedcba9876543210;
- unsigned int i, j;
dst = rte_pktmbuf_alloc(pool);
if (dst == NULL)
ERR_RETURN("Failed to allocate mbuf\n");
dst_data = rte_pktmbuf_mtod(dst, char *);
- for (i = 0; i < RTE_DIM(lengths); i++) {
- /* reset dst_data */
- memset(dst_data, 0, rte_pktmbuf_data_len(dst));
+ for (k = 0; k < ARRAY_SIZE(pattern); k++) {
+ for (i = 0; i < RTE_DIM(lengths); i++) {
+ /* reset dst_data */
+ memset(dst_data, 0, rte_pktmbuf_data_len(dst));
+
+ /* perform the fill operation */
+ int id = rte_dma_fill(dev_id, vchan, pattern[k],
+ rte_pktmbuf_iova(dst), lengths[i], RTE_DMA_OP_FLAG_SUBMIT);
+ if (id < 0) {
+ if (id == -ENOTSUP) {
+ rte_pktmbuf_free(dst);
+ return 0;
+ }
+ ERR_RETURN("Error with rte_dma_fill\n");
+ }
+ await_hw(dev_id, vchan);
- /* perform the fill operation */
- int id = rte_dma_fill(dev_id, vchan, pattern,
- rte_pktmbuf_iova(dst), lengths[i], RTE_DMA_OP_FLAG_SUBMIT);
- if (id < 0)
- ERR_RETURN("Error with rte_dma_fill\n");
- await_hw(dev_id, vchan);
+ if (rte_dma_completed(dev_id, vchan, 1, NULL, NULL) != 1)
+ ERR_RETURN("Error: fill operation failed (length: %u)\n",
+ lengths[i]);
+ /* check the data from the fill operation is correct */
+ for (j = 0; j < lengths[i]; j++) {
+ char pat_byte = ((char *)&pattern[k])[j % 8];
- if (rte_dma_completed(dev_id, vchan, 1, NULL, NULL) != 1)
- ERR_RETURN("Error: fill operation failed (length: %u)\n", lengths[i]);
- /* check the data from the fill operation is correct */
- for (j = 0; j < lengths[i]; j++) {
- char pat_byte = ((char *)&pattern)[j % 8];
- if (dst_data[j] != pat_byte)
- ERR_RETURN("Error with fill operation (lengths = %u): got (%x), not (%x)\n",
- lengths[i], dst_data[j], pat_byte);
+ if (dst_data[j] != pat_byte)
+ ERR_RETURN("Error with fill operation (lengths = %u): got (%x), not (%x)\n",
+ lengths[i], dst_data[j], pat_byte);
+ }
+ /* check that the data after the fill operation was not written to */
+ for (; j < rte_pktmbuf_data_len(dst); j++)
+ if (dst_data[j] != 0)
+ ERR_RETURN("Error, fill operation wrote too far (lengths = %u): got (%x), not (%x)\n",
+ lengths[i], dst_data[j], 0);
}
- /* check that the data after the fill operation was not written to */
- for (; j < rte_pktmbuf_data_len(dst); j++)
- if (dst_data[j] != 0)
- ERR_RETURN("Error, fill operation wrote too far (lengths = %u): got (%x), not (%x)\n",
- lengths[i], dst_data[j], 0);
}
rte_pktmbuf_free(dst);
--
2.34.1
^ permalink raw reply related
* RE: |WARNING| [v5] graph: add optional profiling stats
From: Morten Brørup @ 2026-06-22 7:08 UTC (permalink / raw)
To: dpdklab, test-report, dev, Jerin Jacob, Kiran Kumar K,
Nithin Dabilpuram, Zhirun Yan
In-Reply-To: <6a3846f1.bcbae00d.1a8c6d.fd01SMTPIN_ADDED_MISSING@mx.google.com>
> From: dpdklab@iol.unh.edu [mailto:dpdklab@iol.unh.edu]
> Sent: Sunday, 21 June 2026 22.18
>
> Test-Label: ai-code-review
> Test-Status: WARNING
> https://dpdk.org/patch/165897
>
> _AI Code Review_
>
> === Patch Review: series.patch (via Claude) ===
> Review date: 2026-06-21
>
> # DPDK Patch Review
>
> ## Summary
>
> This patch adds optional profiling statistics to the graph library. The
> code is generally well-structured, but there are several issues that
> need to be addressed.
>
> ---
>
> ## Errors
>
> ### 1. Integer signedness mismatch in RTE_MAX call (Correctness)
>
> **File:** `lib/graph/graph_debug.c`
>
> **Issue:** `RTE_MAX` is used with `INT64_C(0)` (signed) and unsigned
> integer arithmetic results.
Rubbish.
The second parameter passed to RTE_MAX() is explicitly cast to signed integer (int64_t).
> This can cause incorrect comparisons when
> the unsigned result is large enough to be interpreted as negative when
> cast to signed.
>
> ```c
> calls = RTE_MAX(INT64_C(0), (int64_t)(n->total_calls -
> (n->usage_stats[0].calls + n->usage_stats[1].calls)));
> uint64_t cycles = RTE_MAX(INT64_C(0), (int64_t)(n->total_cycles -
> (n->usage_stats[0].cycles + n->usage_stats[1].cycles)));
> uint64_t objs = RTE_MAX(INT64_C(0), (int64_t)(n->total_objs -
> n->usage_stats[1].calls));
> ```
>
> **Why it matters:** If the subtraction underflows (e.g., due to
> uninitialized stats or race conditions), casting a large unsigned value
> to `int64_t` produces a negative number, which `RTE_MAX` correctly
> clamps to 0. However, the result is then assigned back to `uint64_t`,
> where `-1` would become `UINT64_MAX`. While the current code happens to
> work, mixing signed and unsigned types in this way is fragile.
Rubbish.
When clamping to 0, it cannot be -1.
>
> **Suggested fix:** Either use unsigned saturating subtraction or add a
> comment explaining the intentional signed clamping:
>
> ```c
> /* Clamp to 0 if stats haven't been fully initialized */
> calls = (uint64_t)RTE_MAX(INT64_C(0), (int64_t)(n->total_calls -
> (n->usage_stats[0].calls + n->usage_stats[1].calls)));
> ```
>
> Or use a more explicit pattern:
>
> ```c
> uint64_t sum_calls = n->usage_stats[0].calls + n->usage_stats[1].calls;
> calls = (n->total_calls > sum_calls) ? (n->total_calls - sum_calls) :
> 0;
> ```
>
> ---
>
> ### 2. Missing release notes entry
>
> **Issue:** This patch adds a new build-time configuration option
> (`RTE_GRAPH_PROFILE`) and new profiling features, but does not update
> the release notes.
>
> **Why it matters:** DPDK contribution guidelines require release notes
> for significant changes, especially new features and configuration
> options.
Disagree.
IMHO, this option is not significant enough to mention in the release notes.
The overall profiling details are already shown.
This option only adds profiling details for a few specific burst sizes.
>
> **Suggested fix:** Add an entry to
> `doc/guides/rel_notes/release_26_07.rst` (or the appropriate release
> notes file) documenting:
> - The new `RTE_GRAPH_PROFILE` configuration option
> - What profiling statistics it enables
> - Performance impact when enabled
>
> ---
>
> ### 3. `RTE_GRAPH_PROFILE` not defined as commented-out in rte_config.h
>
> **File:** `config/rte_config.h`
>
> **Issue:** The patch adds a comment `/* RTE_GRAPH_PROFILE is not set
> */`, but for consistency with other disabled options in DPDK (and to
> support build system detection), it should be defined to 0 or use
> `#undef`.
>
> ```c
> /* RTE_GRAPH_PROFILE is not set */
> ```
>
> **Why it matters:** DPDK coding standards (per AGENTS.md) specify that
> disabled config options should use `// XXX is not set` format or be
> explicitly set to 0 for clarity.
Rubbish.
It follows the existing coding style in that file.
>
> **Suggested fix:**
>
> ```c
> // RTE_GRAPH_PROFILE is not set
> ```
>
> Or define it explicitly:
>
> ```c
> /* #define RTE_GRAPH_PROFILE 1 */
> ```
>
> ---
>
> ## Warnings
>
> ### 1. Inconsistent format specifier for total_calls
>
> **File:** `lib/graph/graph_debug.c`
>
> **Before:**
> ```c
> fprintf(f, " total_calls=%" PRId64 "\n", n->total_calls);
> ```
>
> **After:**
> ```c
> fprintf(f, " total_calls=%" PRIu64 "\n", n->total_calls);
> ```
>
> **Issue:** This change from `PRId64` to `PRIu64` is correct (since
> `total_calls` is unsigned), but it's technically unrelated to the
> profiling feature addition. Consider splitting this bugfix into a
> separate preparatory patch.
>
> **Suggested action:** Either mention this fix in the commit message or
> split it into a separate bugfix patch with a `Fixes:` tag.
Disagree.
IMO, such minor drive-by changes like this should not be mentioned.
Mentioning them would be noise, and take focus from the actual changes.
>
> ---
>
> ### 2. Potential cache line alignment impact not documented
>
> **File:** `lib/graph/rte_graph_worker_common.h`
>
> **Issue:** When `RTE_GRAPH_PROFILE` is enabled, the `rte_node`
> structure grows significantly (adds ~64 bytes for profiling stats). The
> patch removes the compile-time assertion checking that node metadata
> fits in one cache line.
>
> ```c
> #ifndef RTE_GRAPH_PROFILE
> /* Limit Node specific metadata to one cacheline on 64B CL machine */
> RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
> offsetof(struct rte_node, ctx)) !=
> RTE_CACHE_LINE_MIN_SIZE);
> #endif
> ```
>
> **Why it matters:** This increases memory footprint and potentially
> impacts cache performance. The documentation update mentions enabling
> profiling but doesn't warn about the performance cost.
>
> **Suggested fix:** Add a note in the documentation
> (prog_guide/graph_lib.rst) about the cache line impact:
>
> ```rst
> - Enable the ``RTE_GRAPH_PROFILE`` config option for detailed profiling
> statistics.
> Note: This increases the ``rte_node`` structure size and may impact
> cache performance.
> ```
Disagree.
The memory footprint increase is completely insignificant.
Yes, there's a potential performance cost; but not mainly from the increased structure size.
Any added instrumentation comes with a performance cost, which I consider too obvious to mention.
>
> ---
>
> ### 3. Division by zero checks use ternary instead of explicit if
>
> **File:** `lib/graph/graph_debug.c`
>
> **Issue:** Multiple instances use ternary operators for division-by-
> zero protection:
>
> ```c
> calls == 0 ? 0.0 : (double)cycles / (double)calls
> ```
>
> **Why it matters:** While correct, explicit `if` statements are
> generally more readable for complex calculations, especially when the
> expression appears multiple times.
>
> **Suggested fix:** This is acceptable as-is for simple cases, but
> consider extracting repeated calculations to helper functions if this
> pattern becomes more complex in the future.
>
Disagree.
It's a matter of taste.
In this case, I think the ternary is easier to read.
> ---
>
> ## Info
>
> ### 1. Consider helper macro for safe division
>
> **Observation:** The pattern `calls == 0 ? 0.0 : (double)cycles /
> (double)calls` appears many times.
>
> **Suggestion:** Consider defining a helper macro at the top of the
> file:
>
> ```c
> #define SAFE_DIV(num, den) ((den) == 0 ? 0.0 : (double)(num) /
> (double)(den))
> ```
>
> Then use: `SAFE_DIV(cycles, calls)`
>
> This would reduce code duplication and make the division-by-zero
> protection more obvious.
Disagree.
Again, it's a matter of taste.
In this case, I think the ternary is easier to read.
>
> ---
>
> ### 2. Profiling statistics initialization
>
> **Observation:** The new profiling fields in `rte_node` are not
> explicitly initialized in the patch.
>
> **Question:** Are these fields zeroed during node creation? If they
> rely on `rte_zmalloc()` or similar, this should be verified. If nodes
> are allocated differently, explicit initialization may be needed.
>
> **Suggested verification:** Confirm that node allocation zero-
> initializes the structure, or add explicit initialization in `node.c`.
The node is allocated with calloc() in node.c.
No need for further initialization.
>
> ---
>
> ### 3. Half-burst tracking precision
>
> **Observation:** The code tracks exactly `RTE_GRAPH_BURST_SIZE / 2` and
> `RTE_GRAPH_BURST_SIZE` but not other common burst sizes.
>
> **Suggestion:** Consider if tracking ranges (e.g., `[2..BURST_SIZE/2-
> 1]`, `[BURST_SIZE/2+1..BURST_SIZE-1]`) would provide more complete
> profiling data. The current approach gives precise data for three
> specific cases (0, 1, half, full) and aggregates everything else into
> "more."
>
> This is not a defect, just a design consideration for future
> enhancement.
Tracking ranges does not provide more information.
Tracking specific burst sizes provide relevant information.
Larger burst sizes approximately fit into: cycles = A + B * nb_objs.
Burst sizes of 0 and 1 are frequent instances; they usually don't fit on the linear approximation for larger burst sizes, so tracking them separately provides relevant information.
>
> ---
>
> ## Conclusion
>
> The patch is well-implemented overall with good documentation and
> appropriate use of conditional compilation. The main issues are:
>
> 1. **Error:** Mixed signed/unsigned integer comparison needs
> clarification or refactoring
> 2. **Error:** Missing release notes entry
> 3. **Error:** Config file comment format should follow DPDK convention
> 4. **Warning:** Performance impact of cache line expansion should be
> documented
>
> After addressing these issues, the patch will be ready for integration.
My conclusion:
No changes required. The patch is ready for integration as is.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox