* [PATCH v7 12/16] bus/dpaa: improve log macro and fix bus detection
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260703124950.1895871-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.
Make dpaa_bus_dev_compare() a pure comparator: move the sysfs path
check, dpaa_bus.detected assignment, and pthread_key_create() call
back to rte_dpaa_bus_scan() where they belong. Having side effects
in a comparator causes incorrect behavior when the function is called
multiple times -- it returns 0 (match) for all calls after the first.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/fman/fman.c | 9 ++++-----
drivers/bus/dpaa/dpaa_bus.c | 12 ++++++------
2 files changed, 10 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 54779f82f7..73a7e73a0b 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -54,6 +54,9 @@
/* At present we allow up to 4 push mode queues as default - as each of
* this queue need dedicated portal and we are short of portals.
*/
+#define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
+#define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
+
#define DPAA_MAX_PUSH_MODE_QUEUE 8
#define DPAA_DEFAULT_PUSH_MODE_QUEUE 4
@@ -667,8 +670,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 +716,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 v7 11/16] net/dpaa: optimize FM deconfig
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260703124950.1895871-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_flow.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_flow.c b/drivers/net/dpaa/dpaa_flow.c
index a10ca0cb56..1576134a39 100644
--- a/drivers/net/dpaa/dpaa_flow.c
+++ b/drivers/net/dpaa/dpaa_flow.c
@@ -725,6 +725,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) {
@@ -784,10 +787,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 v7 10/16] drivers: add BMI Tx statistics
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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/dpaa_bus_base_symbols.c | 1 +
drivers/bus/dpaa/include/fman.h | 24 ++++++++++++++++++++++++
drivers/net/dpaa/dpaa_ethdev.h | 11 +++++++++--
4 files changed, 34 insertions(+), 4 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/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index 02b245cd50..d5609bc40d 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>
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.h b/drivers/net/dpaa/dpaa_ethdev.h
index 195b77ab75..d3e005b556 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__
@@ -241,7 +241,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*/
@@ -252,6 +251,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 v7 09/16] net/dpaa: add ONIC port checks
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Vanshika Shukla
In-Reply-To: <20260703124950.1895871-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.
Also remove the fif parameter from dpaa_port_vsp_cleanup() since the
function only uses the port pointer, and simplify the dpaa_flow.c
VSP cleanup call sites accordingly.
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
drivers/net/dpaa/dpaa_ethdev.c | 111 ++++++++++++++++++++++++------
drivers/net/dpaa/dpaa_ethdev.h | 11 ++-
drivers/net/dpaa/dpaa_flow.c | 120 +++++++++++++++++----------------
drivers/net/dpaa/dpaa_flow.h | 7 +-
4 files changed, 166 insertions(+), 83 deletions(-)
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 967e814b5d..d6a21b6ce8 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 */
@@ -482,7 +482,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);
}
@@ -505,7 +505,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();
@@ -520,10 +520,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);
+ }
}
}
@@ -567,29 +569,72 @@ 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;
+ /** 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);
+ 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) {
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;
}
@@ -611,6 +656,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) {
@@ -619,7 +668,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);
@@ -1079,8 +1128,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 &&
+ bpid != dpaa_intf->vsp[vsp_id].vsp_bp[0]->bpid) {
DPAA_PMD_ERR("Various MPs are assigned to RXQs with same VSP");
return -1;
@@ -1117,12 +1166,15 @@ 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);
- /* 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) {
@@ -1174,9 +1226,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;
@@ -1189,11 +1241,12 @@ 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_intf->vsp[0].vsp_bp[0]->bpid =
DPAA_MEMPOOL_TO_POOL_INFO(mp)->bpid;
}
@@ -1426,6 +1479,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)",
@@ -2356,6 +2415,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];
@@ -2498,6 +2564,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;
@@ -2677,6 +2745,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 = rte_eth_dev_allocated(dpaa_dev->device.name);
dpaa_eth_dev_close(eth_dev);
ret = rte_eth_dev_release_port(eth_dev);
diff --git a/drivers/net/dpaa/dpaa_ethdev.h b/drivers/net/dpaa/dpaa_ethdev.h
index f400030a5c..195b77ab75 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 417b9b6fbb..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>
@@ -805,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;
}
@@ -938,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;
@@ -972,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
@@ -1000,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;
}
@@ -1020,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;
+ }
- if (dpaa_intf->vsp_handle[vsp_id]) {
- ret = fm_vsp_free(dpaa_intf->vsp_handle[vsp_id]);
+ vsp = &dpaa_intf->vsp[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)
@@ -1050,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 v7 08/16] bus/dpaa: add DPAA cgrid cleanup support
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index bb308e0d61..02b245cd50 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_alloc_pool_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_alloc_cgrid_range)
RTE_EXPORT_INTERNAL_SYMBOL(qman_release_cgrid_range)
RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_qm_channel_pool_num)
+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
--
2.25.1
^ permalink raw reply related
* [PATCH v7 07/16] bus/dpaa: enhance DPAA FQ shutdown
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Gagandeep Singh
In-Reply-To: <20260703124950.1895871-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 | 78 ++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 21 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 42618c1ab4..ac8b724d65 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,36 @@ 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);
+}
--
2.25.1
^ permalink raw reply related
* [PATCH v7 06/16] bus/dpaa: improve FQ shutdown with channel validation
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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 | 1 +
drivers/bus/dpaa/include/fsl_qman.h | 8 ++--
4 files changed, 53 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..bb308e0d61 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -55,6 +55,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(dpaa_get_qm_channel_pool_num)
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 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 v7 05/16] bus/dpaa: shutdown DPAA FQ by fq descriptor
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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 ++++++++++-
2 files changed, 15 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
--
2.25.1
^ permalink raw reply related
* [PATCH v7 04/16] bus/dpaa: define helpers for qman channel and wq
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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 v7 03/16] drivers: add process-type guards for secondary process
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Prashant Gupta
In-Reply-To: <20260703124950.1895871-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 | 31 +++++++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.c b/drivers/crypto/dpaa_sec/dpaa_sec.c
index c53ee70853..5caf6b18dc 100644
--- a/drivers/crypto/dpaa_sec/dpaa_sec.c
+++ b/drivers/crypto/dpaa_sec/dpaa_sec.c
@@ -3782,9 +3782,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;
-
cryptodev = rte_cryptodev_pmd_create(dpaa_dev->name, &dpaa_dev->device, &init_params);
if (cryptodev == NULL) {
DPAA_SEC_ERR("failed to create cryptodev vdev");
diff --git a/drivers/dma/dpaa/dpaa_qdma.c b/drivers/dma/dpaa/dpaa_qdma.c
index a695f58bc5..6a4022c652 100644
--- a/drivers/dma/dpaa/dpaa_qdma.c
+++ b/drivers/dma/dpaa/dpaa_qdma.c
@@ -9,8 +9,14 @@
#include "dpaa_qdma.h"
#include "dpaa_qdma_logs.h"
-static uint32_t s_sg_max_entry_sz = 2000;
+static int s_data_validation;
static bool s_hw_err_check;
+static int s_sg_enable = 1;
+static uint32_t s_sg_max_entry_sz = 2000;
+
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+static int s_pci_read = 1;
+#endif
#define DPAA_DMA_ERROR_CHECK "dpaa_dma_err_check"
@@ -1346,11 +1352,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;
--
2.25.1
^ permalink raw reply related
* [PATCH v7 02/16] bus/dpaa: scan max BPID from DTS
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-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 v7 01/16] bus/dpaa: refine fman naming and fix global scope
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: Jun Yang
In-Reply-To: <20260703124950.1895871-1-hemant.agrawal@nxp.com>
From: Jun Yang <jun.yang@nxp.com>
Rename ccsr_map to memac_map in __fman_if struct for clarity,
as it maps the MEMAC register space not generic CCSR.
Rename bmi_map to rx_bmi_map to distinguish from TX BMI.
Make fman_ccsr_map_fd static as it is only used within fman.c.
Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
drivers/bus/dpaa/base/fman/fman.c | 14 ++--
drivers/bus/dpaa/base/fman/fman_hw.c | 106 ++++++++++++++-------------
drivers/bus/dpaa/include/fman.h | 6 +-
3 files changed, 63 insertions(+), 63 deletions(-)
diff --git a/drivers/bus/dpaa/base/fman/fman.c b/drivers/bus/dpaa/base/fman/fman.c
index 55311235f5..55f466d751 100644
--- a/drivers/bus/dpaa/base/fman/fman.c
+++ b/drivers/bus/dpaa/base/fman/fman.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
*
* Copyright 2010-2016 Freescale Semiconductor Inc.
- * Copyright 2017-2024 NXP
+ * Copyright 2017-2026 NXP
*
*/
@@ -465,9 +465,9 @@ fman_if_init(const struct device_node *dpa_node, int fd)
mname, regs_addr);
goto err;
}
- __if->ccsr_map = mmap(NULL, __if->regs_size,
+ __if->memac_map = mmap(NULL, __if->regs_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, phys_addr);
- if (__if->ccsr_map == MAP_FAILED) {
+ if (__if->memac_map == MAP_FAILED) {
FMAN_ERR(-errno, "mmap(0x%"PRIx64")", phys_addr);
goto err;
}
@@ -599,9 +599,9 @@ fman_if_init(const struct device_node *dpa_node, int fd)
goto err;
}
- __if->bmi_map = mmap(NULL, __if->regs_size,
+ __if->rx_bmi_map = mmap(NULL, __if->regs_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, phys_addr);
- if (__if->bmi_map == MAP_FAILED) {
+ if (__if->rx_bmi_map == MAP_FAILED) {
FMAN_ERR(-errno, "mmap(0x%"PRIx64")", phys_addr);
goto err;
}
@@ -1167,13 +1167,13 @@ fman_finish(void)
}
/* disable Rx and Tx */
- regs = __if->ccsr_map;
+ regs = __if->memac_map;
cfg = in_be32(®s->command_config);
out_be32(®s->command_config,
cfg & (~(MEMAC_RX_ENABLE | MEMAC_TX_ENABLE)));
/* release the mapping */
- _errno = munmap(__if->ccsr_map, __if->regs_size);
+ _errno = munmap(__if->memac_map, __if->regs_size);
if (unlikely(_errno < 0))
FMAN_ERR(_errno, "munmap() = (%s)", strerror(errno));
DPAA_BUS_INFO("Tearing down %s", __if->node_path);
diff --git a/drivers/bus/dpaa/base/fman/fman_hw.c b/drivers/bus/dpaa/base/fman/fman_hw.c
index cbb0491d70..ce68581555 100644
--- a/drivers/bus/dpaa/base/fman/fman_hw.c
+++ b/drivers/bus/dpaa/base/fman/fman_hw.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright 2017,2020,2022-2023 NXP
+ * Copyright 2017,2020,2022-2023,2026 NXP
*
*/
@@ -16,6 +16,8 @@
#include <fsl_fman_crc64.h>
#include <fsl_bman.h>
+extern int fman_ccsr_map_fd;
+
#define FMAN_SP_SG_DISABLE 0x80000000
#define FMAN_SP_EXT_BUF_MARG_START_SHIFT 16
@@ -39,7 +41,7 @@ fman_if_set_mcast_filter_table(struct fman_if *p)
void *hashtable_ctrl;
uint32_t i;
- hashtable_ctrl = &((struct memac_regs *)__if->ccsr_map)->hashtable_ctrl;
+ hashtable_ctrl = &((struct memac_regs *)__if->memac_map)->hashtable_ctrl;
for (i = 0; i < 64; i++)
out_be32(hashtable_ctrl, i|HASH_CTRL_MCAST_EN);
}
@@ -51,7 +53,7 @@ fman_if_reset_mcast_filter_table(struct fman_if *p)
void *hashtable_ctrl;
uint32_t i;
- hashtable_ctrl = &((struct memac_regs *)__if->ccsr_map)->hashtable_ctrl;
+ hashtable_ctrl = &((struct memac_regs *)__if->memac_map)->hashtable_ctrl;
for (i = 0; i < 64; i++)
out_be32(hashtable_ctrl, i & ~HASH_CTRL_MCAST_EN);
}
@@ -101,7 +103,7 @@ fman_if_add_hash_mac_addr(struct fman_if *p, uint8_t *eth)
hash = get_mac_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
hash = hash | HASH_CTRL_MCAST_EN;
- hashtable_ctrl = &((struct memac_regs *)__if->ccsr_map)->hashtable_ctrl;
+ hashtable_ctrl = &((struct memac_regs *)__if->memac_map)->hashtable_ctrl;
out_be32(hashtable_ctrl, hash);
return 0;
@@ -112,7 +114,7 @@ fman_if_get_primary_mac_addr(struct fman_if *p, uint8_t *eth)
{
struct __fman_if *__if = container_of(p, struct __fman_if, __if);
void *mac_reg =
- &((struct memac_regs *)__if->ccsr_map)->mac_addr0.mac_addr_l;
+ &((struct memac_regs *)__if->memac_map)->mac_addr0.mac_addr_l;
u32 val = in_be32(mac_reg);
int i;
@@ -130,7 +132,7 @@ fman_if_get_primary_mac_addr(struct fman_if *p, uint8_t *eth)
eth[2] = (val & 0x00ff0000) >> 16;
eth[3] = (val & 0xff000000) >> 24;
- mac_reg = &((struct memac_regs *)__if->ccsr_map)->mac_addr0.mac_addr_u;
+ mac_reg = &((struct memac_regs *)__if->memac_map)->mac_addr0.mac_addr_u;
val = in_be32(mac_reg);
eth[4] = (val & 0x000000ff) >> 0;
@@ -151,16 +153,16 @@ fman_if_clear_mac_addr(struct fman_if *p, uint8_t addr_num)
return;
if (addr_num) {
- reg = &((struct memac_regs *)m->ccsr_map)->
+ reg = &((struct memac_regs *)m->memac_map)->
mac_addr[addr_num-1].mac_addr_l;
out_be32(reg, 0x0);
- reg = &((struct memac_regs *)m->ccsr_map)->
+ reg = &((struct memac_regs *)m->memac_map)->
mac_addr[addr_num-1].mac_addr_u;
out_be32(reg, 0x0);
} else {
- reg = &((struct memac_regs *)m->ccsr_map)->mac_addr0.mac_addr_l;
+ reg = &((struct memac_regs *)m->memac_map)->mac_addr0.mac_addr_l;
out_be32(reg, 0x0);
- reg = &((struct memac_regs *)m->ccsr_map)->mac_addr0.mac_addr_u;
+ reg = &((struct memac_regs *)m->memac_map)->mac_addr0.mac_addr_u;
out_be32(reg, 0x0);
}
}
@@ -180,10 +182,10 @@ fman_if_add_mac_addr(struct fman_if *p, uint8_t *eth, uint8_t addr_num)
memcpy(&m->__if.mac_addr, eth, ETHER_ADDR_LEN);
if (addr_num)
- reg = &((struct memac_regs *)m->ccsr_map)->
+ reg = &((struct memac_regs *)m->memac_map)->
mac_addr[addr_num-1].mac_addr_l;
else
- reg = &((struct memac_regs *)m->ccsr_map)->mac_addr0.mac_addr_l;
+ reg = &((struct memac_regs *)m->memac_map)->mac_addr0.mac_addr_l;
val = (m->__if.mac_addr.addr_bytes[0] |
(m->__if.mac_addr.addr_bytes[1] << 8) |
@@ -192,10 +194,10 @@ fman_if_add_mac_addr(struct fman_if *p, uint8_t *eth, uint8_t addr_num)
out_be32(reg, val);
if (addr_num)
- reg = &((struct memac_regs *)m->ccsr_map)->
+ reg = &((struct memac_regs *)m->memac_map)->
mac_addr[addr_num-1].mac_addr_u;
else
- reg = &((struct memac_regs *)m->ccsr_map)->mac_addr0.mac_addr_u;
+ reg = &((struct memac_regs *)m->memac_map)->mac_addr0.mac_addr_u;
val = ((m->__if.mac_addr.addr_bytes[4] << 0) |
(m->__if.mac_addr.addr_bytes[5] << 8));
@@ -214,7 +216,7 @@ fman_if_set_rx_ignore_pause_frames(struct fman_if *p, bool enable)
assert(fman_ccsr_map_fd != -1);
/* Set Rx Ignore Pause Frames */
- cmdcfg = &((struct memac_regs *)__if->ccsr_map)->command_config;
+ cmdcfg = &((struct memac_regs *)__if->memac_map)->command_config;
if (enable)
value = in_be32(cmdcfg) | CMD_CFG_PAUSE_IGNORE;
else
@@ -232,7 +234,7 @@ fman_if_conf_max_frame_len(struct fman_if *p, unsigned int max_frame_len)
assert(fman_ccsr_map_fd != -1);
/* Set Max frame length */
- maxfrm = &((struct memac_regs *)__if->ccsr_map)->maxfrm;
+ maxfrm = &((struct memac_regs *)__if->memac_map)->maxfrm;
out_be32(maxfrm, (MAXFRM_RX_MASK & max_frame_len));
}
@@ -240,7 +242,7 @@ void
fman_if_stats_get(struct fman_if *p, struct rte_eth_stats *stats)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct memac_regs *regs = m->ccsr_map;
+ struct memac_regs *regs = m->memac_map;
/* read recved packet count */
stats->ipackets = (u64)in_be32(®s->rfrm_l) |
@@ -263,7 +265,7 @@ void
fman_if_stats_get_all(struct fman_if *p, uint64_t *value, int n)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct memac_regs *regs = m->ccsr_map;
+ struct memac_regs *regs = m->memac_map;
int i;
uint64_t base_offset = offsetof(struct memac_regs, reoct_l);
@@ -278,7 +280,7 @@ void
fman_if_stats_reset(struct fman_if *p)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct memac_regs *regs = m->ccsr_map;
+ struct memac_regs *regs = m->memac_map;
uint32_t tmp;
tmp = in_be32(®s->statn_config);
@@ -295,7 +297,7 @@ void
fman_if_bmi_stats_enable(struct fman_if *p)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->bmi_map;
+ struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->rx_bmi_map;
uint32_t tmp;
tmp = in_be32(®s->fmbm_rstc);
@@ -309,7 +311,7 @@ void
fman_if_bmi_stats_disable(struct fman_if *p)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->bmi_map;
+ struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->rx_bmi_map;
uint32_t tmp;
tmp = in_be32(®s->fmbm_rstc);
@@ -323,7 +325,7 @@ void
fman_if_bmi_stats_get_all(struct fman_if *p, uint64_t *value)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->bmi_map;
+ struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->rx_bmi_map;
int i = 0;
value[i++] = (u32)in_be32(®s->fmbm_rfrc);
@@ -340,7 +342,7 @@ void
fman_if_bmi_stats_reset(struct fman_if *p)
{
struct __fman_if *m = container_of(p, struct __fman_if, __if);
- struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->bmi_map;
+ struct rx_bmi_regs *regs = (struct rx_bmi_regs *)m->rx_bmi_map;
out_be32(®s->fmbm_rfrc, 0);
out_be32(®s->fmbm_rfbc, 0);
@@ -361,7 +363,7 @@ fman_if_promiscuous_enable(struct fman_if *p)
assert(fman_ccsr_map_fd != -1);
/* Enable Rx promiscuous mode */
- cmdcfg = &((struct memac_regs *)__if->ccsr_map)->command_config;
+ cmdcfg = &((struct memac_regs *)__if->memac_map)->command_config;
out_be32(cmdcfg, in_be32(cmdcfg) | CMD_CFG_PROMIS_EN);
}
@@ -374,7 +376,7 @@ fman_if_promiscuous_disable(struct fman_if *p)
assert(fman_ccsr_map_fd != -1);
/* Disable Rx promiscuous mode */
- cmdcfg = &((struct memac_regs *)__if->ccsr_map)->command_config;
+ cmdcfg = &((struct memac_regs *)__if->memac_map)->command_config;
out_be32(cmdcfg, in_be32(cmdcfg) & (~CMD_CFG_PROMIS_EN));
}
@@ -386,7 +388,7 @@ fman_if_enable_rx(struct fman_if *p)
assert(fman_ccsr_map_fd != -1);
/* enable Rx and Tx */
- out_be32(__if->ccsr_map + 8, in_be32(__if->ccsr_map + 8) | 3);
+ out_be32(__if->memac_map + 8, in_be32(__if->memac_map + 8) | 3);
}
void
@@ -397,7 +399,7 @@ fman_if_disable_rx(struct fman_if *p)
assert(fman_ccsr_map_fd != -1);
/* only disable Rx, not Tx */
- out_be32(__if->ccsr_map + 8, in_be32(__if->ccsr_map + 8) & ~(u32)2);
+ out_be32(__if->memac_map + 8, in_be32(__if->memac_map + 8) & ~(u32)2);
}
int
@@ -408,7 +410,7 @@ fman_if_get_rx_status(struct fman_if *p)
assert(fman_ccsr_map_fd != -1);
/* return true if RX bit is set */
- return !!(in_be32(__if->ccsr_map + 8) & (u32)2);
+ return !!(in_be32(__if->memac_map + 8) & (u32)2);
}
void
@@ -421,11 +423,11 @@ fman_if_loopback_enable(struct fman_if *p)
/* Enable loopback mode */
if ((__if->__if.is_memac) && (__if->__if.is_rgmii)) {
unsigned int *ifmode =
- &((struct memac_regs *)__if->ccsr_map)->if_mode;
+ &((struct memac_regs *)__if->memac_map)->if_mode;
out_be32(ifmode, in_be32(ifmode) | IF_MODE_RLP);
} else{
unsigned int *cmdcfg =
- &((struct memac_regs *)__if->ccsr_map)->command_config;
+ &((struct memac_regs *)__if->memac_map)->command_config;
out_be32(cmdcfg, in_be32(cmdcfg) | CMD_CFG_LOOPBACK_EN);
}
}
@@ -439,11 +441,11 @@ fman_if_loopback_disable(struct fman_if *p)
/* Disable loopback mode */
if ((__if->__if.is_memac) && (__if->__if.is_rgmii)) {
unsigned int *ifmode =
- &((struct memac_regs *)__if->ccsr_map)->if_mode;
+ &((struct memac_regs *)__if->memac_map)->if_mode;
out_be32(ifmode, in_be32(ifmode) & ~IF_MODE_RLP);
} else {
unsigned int *cmdcfg =
- &((struct memac_regs *)__if->ccsr_map)->command_config;
+ &((struct memac_regs *)__if->memac_map)->command_config;
out_be32(cmdcfg, in_be32(cmdcfg) & ~CMD_CFG_LOOPBACK_EN);
}
}
@@ -461,11 +463,11 @@ fman_if_set_bp(struct fman_if *fm_if, unsigned num __always_unused,
assert(fman_ccsr_map_fd != -1);
fmbm_ebmpi =
- in_be32(&((struct rx_bmi_regs *)__if->bmi_map)->fmbm_ebmpi[0]);
+ in_be32(&((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_ebmpi[0]);
fmbm_ebmpi = ebmpi_val_ace | (fmbm_ebmpi & ebmpi_mask) | (bpid << 16) |
(bufsize);
- out_be32(&((struct rx_bmi_regs *)__if->bmi_map)->fmbm_ebmpi[0],
+ out_be32(&((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_ebmpi[0],
fmbm_ebmpi);
}
@@ -477,7 +479,7 @@ fman_if_get_fc_threshold(struct fman_if *fm_if)
assert(fman_ccsr_map_fd != -1);
- fmbm_mpd = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_mpd;
+ fmbm_mpd = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_mpd;
return in_be32(fmbm_mpd);
}
@@ -490,7 +492,7 @@ fman_if_set_fc_threshold(struct fman_if *fm_if, u32 high_water,
assert(fman_ccsr_map_fd != -1);
- fmbm_mpd = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_mpd;
+ fmbm_mpd = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_mpd;
out_be32(fmbm_mpd, FMAN_ENABLE_BPOOL_DEPLETION);
return bm_pool_set_hw_threshold(bpid, low_water, high_water);
@@ -503,7 +505,7 @@ fman_if_get_fc_quanta(struct fman_if *fm_if)
assert(fman_ccsr_map_fd != -1);
- return in_be32(&((struct memac_regs *)__if->ccsr_map)->pause_quanta[0]);
+ return in_be32(&((struct memac_regs *)__if->memac_map)->pause_quanta[0]);
}
int
@@ -513,7 +515,7 @@ fman_if_set_fc_quanta(struct fman_if *fm_if, u16 pause_quanta)
assert(fman_ccsr_map_fd != -1);
- out_be32(&((struct memac_regs *)__if->ccsr_map)->pause_quanta[0],
+ out_be32(&((struct memac_regs *)__if->memac_map)->pause_quanta[0],
pause_quanta);
return 0;
}
@@ -528,7 +530,7 @@ fman_if_get_fdoff(struct fman_if *fm_if)
assert(fman_ccsr_map_fd != -1);
- fmbm_rebm = in_be32(&((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rebm);
+ fmbm_rebm = in_be32(&((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rebm);
fdoff = (fmbm_rebm >> FMAN_SP_EXT_BUF_MARG_START_SHIFT) & 0x1ff;
@@ -543,7 +545,7 @@ fman_if_set_err_fqid(struct fman_if *fm_if, uint32_t err_fqid)
assert(fman_ccsr_map_fd != -1);
unsigned int *fmbm_refqid =
- &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_refqid;
+ &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_refqid;
out_be32(fmbm_refqid, err_fqid);
}
@@ -559,7 +561,7 @@ fman_if_get_ic_params(struct fman_if *fm_if, struct fman_if_ic_params *icp)
assert(fman_ccsr_map_fd != -1);
unsigned int *fmbm_ricp =
- &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_ricp;
+ &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_ricp;
val = in_be32(fmbm_ricp);
icp->iceof = (val & iceof_mask) >> 12;
@@ -586,7 +588,7 @@ fman_if_set_ic_params(struct fman_if *fm_if,
val |= (icp->icsz >> 4) & icsz_mask;
unsigned int *fmbm_ricp =
- &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_ricp;
+ &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_ricp;
out_be32(fmbm_ricp, val);
unsigned int *fmbm_ticp =
@@ -608,7 +610,7 @@ fman_if_set_fdoff(struct fman_if *fm_if, uint32_t fd_offset)
assert(fman_ccsr_map_fd != -1);
- fmbm_rebm = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rebm;
+ fmbm_rebm = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rebm;
out_be32(fmbm_rebm, (in_be32(fmbm_rebm) & ~fmbm_mask) | val);
}
@@ -621,7 +623,7 @@ fman_if_set_maxfrm(struct fman_if *fm_if, uint16_t max_frm)
assert(fman_ccsr_map_fd != -1);
- reg_maxfrm = &((struct memac_regs *)__if->ccsr_map)->maxfrm;
+ reg_maxfrm = &((struct memac_regs *)__if->memac_map)->maxfrm;
out_be32(reg_maxfrm, (in_be32(reg_maxfrm) & 0xFFFF0000) | max_frm);
}
@@ -634,7 +636,7 @@ fman_if_get_maxfrm(struct fman_if *fm_if)
assert(fman_ccsr_map_fd != -1);
- reg_maxfrm = &((struct memac_regs *)__if->ccsr_map)->maxfrm;
+ reg_maxfrm = &((struct memac_regs *)__if->memac_map)->maxfrm;
return (in_be32(reg_maxfrm) | 0x0000FFFF);
}
@@ -655,7 +657,7 @@ fman_if_get_sg_enable(struct fman_if *fm_if)
assert(fman_ccsr_map_fd != -1);
- fmbm_rebm = in_be32(&((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rebm);
+ fmbm_rebm = in_be32(&((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rebm);
return (fmbm_rebm & FMAN_SP_SG_DISABLE) ? 0 : 1;
}
@@ -675,7 +677,7 @@ fman_if_set_sg(struct fman_if *fm_if, int enable)
assert(fman_ccsr_map_fd != -1);
- fmbm_rebm = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rebm;
+ fmbm_rebm = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rebm;
out_be32(fmbm_rebm, (in_be32(fmbm_rebm) & ~fmbm_mask) | val);
}
@@ -699,14 +701,14 @@ fman_if_discard_rx_errors(struct fman_if *fm_if)
struct __fman_if *__if = container_of(fm_if, struct __fman_if, __if);
unsigned int *fmbm_rfsdm, *fmbm_rfsem;
- fmbm_rfsem = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rfsem;
+ fmbm_rfsem = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rfsem;
out_be32(fmbm_rfsem, 0);
/* Configure the discard mask to discard the error packets which have
* DMA errors, Frame size error, Header error etc. The mask 0x010EE3F0
* is to configured discard all the errors which come in the FD[STATUS]
*/
- fmbm_rfsdm = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rfsdm;
+ fmbm_rfsdm = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rfsdm;
out_be32(fmbm_rfsdm, 0x010EE3F0);
}
@@ -718,9 +720,9 @@ fman_if_receive_rx_errors(struct fman_if *fm_if,
unsigned int *fmbm_rcfg, *fmbm_rfsdm, *fmbm_rfsem;
unsigned int val;
- fmbm_rcfg = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rcfg;
- fmbm_rfsdm = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rfsdm;
- fmbm_rfsem = &((struct rx_bmi_regs *)__if->bmi_map)->fmbm_rfsem;
+ fmbm_rcfg = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rcfg;
+ fmbm_rfsdm = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rfsdm;
+ fmbm_rfsem = &((struct rx_bmi_regs *)__if->rx_bmi_map)->fmbm_rfsem;
val = in_be32(fmbm_rcfg);
out_be32(fmbm_rcfg, val | BMI_PORT_CFG_FDOVR);
diff --git a/drivers/bus/dpaa/include/fman.h b/drivers/bus/dpaa/include/fman.h
index c33fe81516..a248edf4d8 100644
--- a/drivers/bus/dpaa/include/fman.h
+++ b/drivers/bus/dpaa/include/fman.h
@@ -462,8 +462,8 @@ struct __fman_if {
char node_name[IF_NAME_MAX_LEN];
char node_path[PATH_MAX];
uint64_t regs_size;
- void *ccsr_map;
- void *bmi_map;
+ void *memac_map;
+ void *rx_bmi_map;
void *tx_bmi_map;
void *qmi_map;
};
@@ -473,8 +473,6 @@ struct __fman_if {
*/
extern const struct list_head *fman_if_list;
-extern int fman_ccsr_map_fd;
-
/* To iterate the "bpool_list" for an interface. Eg;
* struct fman_if *p = get_ptr_to_some_interface();
* struct fman_if_bpool *bp;
--
2.25.1
^ permalink raw reply related
* [PATCH v7 00/16] DPAA bus/net/mempool/DMA driver fixes and improvements
From: Hemant Agrawal @ 2026-07-03 12:49 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260702053359.3243907-1-hemant.agrawal@nxp.com>
This series collects a set of correctness fixes, cleanups and feature
additions across the NXP DPAA bus, net, mempool and DMA drivers.
1. Bus/fman infrastructure cleanups (patches 01, 02, 12)
- bus/dpaa: refine fman naming and fix global scope
- bus/dpaa: scan max BPID from DTS
- bus/dpaa: improve log macro and fix bus detection
2. Process-type guards (patch 03)
- drivers: add process-type guards to prevent segfaults in secondary
3. FQ shutdown hardening (patches 04-08)
- bus/dpaa: define helpers for qman channel and wq
- bus/dpaa: shutdown DPAA FQ by fq descriptor
- bus/dpaa: improve FQ shutdown with channel validation
- bus/dpaa: enhance DPAA FQ shutdown
- bus/dpaa: add DPAA cgrid cleanup support
4. net/dpaa improvements (patches 09, 11, 13)
- net/dpaa: add ONIC port checks
- net/dpaa: optimize FM deconfig
- net/dpaa: optimize FMC MAC type parsing
5. Statistics (patch 10)
- drivers: add BMI Tx statistics
6. mempool/dpaa (patches 14-15)
- drivers: optimize DPAA multi-entry buffer pool operations
- drivers: release DPAA bpid on driver destructor
7. dma/dpaa (patch 16)
- dma/dpaa: add SG data validation and ERR050757 fix
v7 changes:
- Drop three net/dpaa patches from v6 that need further review:
"net/dpaa: clean Tx confirmation FQ on device stop",
"net/dpaa: remove redundant FQ shutdown from Rx queue setup",
"net/dpaa: report error on using deferred start".
- Rebased onto 26.07-rc2.
v6 changes:
- Fix bman_release_fast() in patch 14: replace rte_memcpy() on the
small bm_bufs[] stack array with memcpy(); the SIMD implementation
of rte_memcpy reads in 32/64-byte chunks and triggers
-Warray-bounds with GCC 15 / ASAN builds on the 64-byte array.
memcpy() is correct here as this is a local stack buffer with no
DMA or multi-process constraints.
v5 changes:
- Rebased onto current upstream main; resolved conflict in
drivers/crypto/dpaa_sec/dpaa_sec.c where upstream removed the
cryptodev_name[] local variable and snprintf() call in
cryptodev_dpaa_sec_probe() -- patch 03 now uses dpaa_dev->name
directly in rte_cryptodev_pmd_create().
- Resolved conflict in drivers/net/dpaa/dpaa_ethdev.c where upstream
removed rte_dpaa_device.eth_dev -- patch 03 now uses
rte_eth_dev_allocated() to look up the Ethernet device by name.
v4 changes:
- Fix dpaa_bus_dev_compare() to return the strncmp result (previously
always returned 0, breaking device matching).
- Remove the dead get_tx_port_type() function that triggered a clang
-Wunused-function CI failure.
- Guard all dpaa_fm_deconfig() call sites against NULL port_handle to
prevent a NULL dereference on partially initialised interfaces.
- Move the penv variable declaration in dpaa_qdma_init() to the point of
use (C99 inline), fixing a spurious -Wunused-variable warning during
bisect of earlier patches in the series.
Gagandeep Singh (2):
bus/dpaa: enhance DPAA FQ shutdown
dma/dpaa: add SG data validation and ERR050757 fix
Hemant Agrawal (2):
net/dpaa: optimize FM deconfig
bus/dpaa: improve log macro and fix bus detection
Jun Yang (10):
bus/dpaa: refine fman naming and fix global scope
bus/dpaa: scan max BPID from DTS
bus/dpaa: define helpers for qman channel and wq
bus/dpaa: shutdown DPAA FQ by fq descriptor
bus/dpaa: improve FQ shutdown with channel validation
bus/dpaa: add DPAA cgrid cleanup support
drivers: add BMI Tx statistics
net/dpaa: optimize FMC MAC type parsing
drivers: optimize DPAA multi-entry buffer pool operations
drivers: release DPAA bpid on driver destructor
Prashant Gupta (1):
drivers: add process-type guards for secondary process
Vanshika Shukla (1):
net/dpaa: add ONIC port checks
drivers/bus/dpaa/base/fman/fman.c | 23 ++--
drivers/bus/dpaa/base/fman/fman_hw.c | 108 +++++++++---------
drivers/bus/dpaa/base/qbman/bman.c | 59 ++++------
drivers/bus/dpaa/base/qbman/bman_driver.c | 48 +++++---
drivers/bus/dpaa/base/qbman/qman.c | 113 +++++++++++--------
drivers/bus/dpaa/base/qbman/qman.h | 23 +++-
drivers/bus/dpaa/base/qbman/qman_driver.c | 29 ++++-
drivers/bus/dpaa/dpaa_bus.c | 12 +-
drivers/bus/dpaa/dpaa_bus_base_symbols.c | 4 +
drivers/bus/dpaa/include/fman.h | 30 ++++-
drivers/bus/dpaa/include/fsl_bman.h | 49 ++++++--
drivers/bus/dpaa/include/fsl_qman.h | 22 +++-
drivers/crypto/dpaa_sec/dpaa_sec.c | 3 -
drivers/dma/dpaa/dpaa_qdma.c | 102 +++++++++++++----
drivers/mempool/dpaa/dpaa_mempool.c | 75 +++++++++++--
drivers/mempool/dpaa/dpaa_mempool.h | 3 +-
drivers/net/dpaa/dpaa_ethdev.c | 111 +++++++++++++++----
drivers/net/dpaa/dpaa_ethdev.h | 22 +++-
drivers/net/dpaa/dpaa_flow.c | 129 ++++++++++++----------
drivers/net/dpaa/dpaa_flow.h | 7 +-
drivers/net/dpaa/dpaa_fmc.c | 73 +++++++-----
21 files changed, 697 insertions(+), 348 deletions(-)
--
2.25.1
^ permalink raw reply
* [PATCH v4 5/5] app/testpmd: add pinned external-buffer Rx pool command
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260703121952.1277387-1-dawid.wesierski@intel.com>
Add the 'create pinned-rxpool <seg-idx> <count> <elt-size>' testpmd
command to demonstrate zero-copy header/payload split receive using
pinned external-buffer mempools (RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF).
Motivation: the DPDK buffer-split offload (RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT)
with two Rx segments allows an application to direct the NIC to place
the protocol header and the payload into separate mbufs. Combining it
with a pinned external-buffer pool for the payload segment lets the NIC
DMA the payload directly into application-owned hugepage memory without
any extra copy or new ethdev API.
This is the mechanism needed by streaming applications such as the
Media Transport Library (MTL) for SMPTE ST 2110-21 video reception,
where 1260-byte RTP payload chunks must land zero-copy in pre-allocated
per-frame video buffers. The existing rte_pktmbuf_pool_create_extbuf()
API covers this use case; no new callback or out-of-tree PMD hook is
required.
The command allocates a hugepage region via rte_zmalloc_socket(),
creates a pinned pool over it with rte_pktmbuf_pool_create_extbuf(),
and registers the pool with testpmd's pool index so that
rx_queue_setup() automatically selects it for the configured split
segment. The complete workflow and a worked video-streaming example are
documented in doc/guides/testpmd_app_ug/testpmd_funcs.rst.
Signed-off-by: Dawid Wesierski <dawid.wesierski@intel.com>
Signed-off-by: Marek Kasiewicz <marek.kasiewicz@intel.com>
---
app/test-pmd/cmdline.c | 123 ++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 82 +++++++++++++
2 files changed, 205 insertions(+)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 3c39e27aa8..83ea6d2cd2 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -371,6 +371,11 @@ static void cmd_help_long_parsed(void *parsed_result,
"inner-ipv6-tcp|inner-ipv4-udp|inner-ipv6-udp|"
"inner-ipv4-sctp|inner-ipv6-sctp\n\n"
+ "create pinned-rxpool (seg-idx) (count) (elt-size)\n"
+ " Create a pinned external-buffer Rx mempool for"
+ " buffer-split segment <seg-idx>. Payloads DMA directly"
+ " into application-owned hugepage memory without copy.\n\n"
+
"set txpkts (x[,y]*)\n"
" Set the length of each segment of TXONLY"
" and optionally CSUM packets.\n\n"
@@ -4483,6 +4488,123 @@ static cmdline_parse_inst_t cmd_set_rxhdrs = {
},
};
+/* *** CREATE PINNED EXTERNAL BUFFER POOL FOR RX SPLIT SEGMENT *** */
+struct cmd_create_pinned_rxpool_result {
+ cmdline_fixed_string_t create;
+ cmdline_fixed_string_t pinned_rxpool;
+ uint16_t seg_idx;
+ uint32_t count;
+ uint16_t elt_size;
+};
+
+static void
+cmd_create_pinned_rxpool_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_create_pinned_rxpool_result *res = parsed_result;
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+ struct rte_pktmbuf_extmem ext_mem;
+ struct rte_mempool *mp;
+ unsigned int socket_id;
+ size_t mem_size;
+ void *frames;
+
+ if (res->seg_idx >= MAX_SEGS_BUFFER_SPLIT) {
+ fprintf(stderr, "seg-idx must be less than %u\n",
+ MAX_SEGS_BUFFER_SPLIT);
+ return;
+ }
+
+ socket_id = (num_sockets > 0) ? (unsigned int)socket_ids[0] : 0;
+ mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name),
+ res->seg_idx);
+
+ if (mbuf_pool_find(socket_id, res->seg_idx) != NULL) {
+ fprintf(stderr,
+ "Pool '%s' already exists; stop/close port before recreating\n",
+ pool_name);
+ return;
+ }
+
+ mem_size = (size_t)res->count * res->elt_size;
+ frames = rte_zmalloc_socket("pinned_rxpool_mem", mem_size,
+ RTE_CACHE_LINE_SIZE, socket_id);
+ if (frames == NULL) {
+ fprintf(stderr,
+ "Failed to allocate %zu bytes for pinned pool\n",
+ mem_size);
+ return;
+ }
+
+ ext_mem.buf_ptr = frames;
+ ext_mem.buf_iova = rte_malloc_virt2iova(frames);
+ if (ext_mem.buf_iova == RTE_BAD_IOVA) {
+ fprintf(stderr,
+ "No IOVA mapping for pinned pool (VFIO/IOMMU required)\n");
+ rte_free(frames);
+ return;
+ }
+ ext_mem.buf_len = mem_size;
+ ext_mem.elt_size = res->elt_size;
+
+ mp = rte_pktmbuf_pool_create_extbuf(pool_name, res->count,
+ 0, 0, res->elt_size,
+ socket_id, &ext_mem, 1);
+ if (mp == NULL) {
+ fprintf(stderr, "Failed to create pinned pool '%s': %s\n",
+ pool_name, rte_strerror(rte_errno));
+ rte_free(frames);
+ return;
+ }
+
+ /* Register with testpmd so rx_queue_setup() uses this pool for
+ * segment <seg_idx> when buffer-split is configured.
+ */
+ mbuf_data_size[res->seg_idx] = res->elt_size;
+ if ((uint32_t)(res->seg_idx + 1) > mbuf_data_size_n)
+ mbuf_data_size_n = res->seg_idx + 1;
+
+ printf("Created pinned ext-buf pool '%s':\n"
+ " socket=%u seg-idx=%u count=%u elt-size=%u "
+ "mem=%p iova=0x%" PRIx64 "\n",
+ pool_name, socket_id, res->seg_idx, res->count,
+ res->elt_size, frames, ext_mem.buf_iova);
+}
+
+static cmdline_parse_token_string_t cmd_create_pinned_rxpool_create =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_pinned_rxpool_result,
+ create, "create");
+static cmdline_parse_token_string_t cmd_create_pinned_rxpool_kw =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_pinned_rxpool_result,
+ pinned_rxpool, "pinned-rxpool");
+static cmdline_parse_token_num_t cmd_create_pinned_rxpool_seg_idx =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_pinned_rxpool_result,
+ seg_idx, RTE_UINT16);
+static cmdline_parse_token_num_t cmd_create_pinned_rxpool_count =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_pinned_rxpool_result,
+ count, RTE_UINT32);
+static cmdline_parse_token_num_t cmd_create_pinned_rxpool_elt_size =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_pinned_rxpool_result,
+ elt_size, RTE_UINT16);
+
+static cmdline_parse_inst_t cmd_create_pinned_rxpool = {
+ .f = cmd_create_pinned_rxpool_parsed,
+ .data = NULL,
+ .help_str = "create pinned-rxpool <seg-idx> <count> <elt-size>: "
+ "create a pinned external-buffer Rx mempool for split "
+ "segment <seg-idx>; payloads DMA directly into hugepage "
+ "memory owned by the application without an extra copy",
+ .tokens = {
+ (void *)&cmd_create_pinned_rxpool_create,
+ (void *)&cmd_create_pinned_rxpool_kw,
+ (void *)&cmd_create_pinned_rxpool_seg_idx,
+ (void *)&cmd_create_pinned_rxpool_count,
+ (void *)&cmd_create_pinned_rxpool_elt_size,
+ NULL,
+ },
+};
+
/* *** SET SEGMENT LENGTHS OF TXONLY PACKETS *** */
struct cmd_set_txpkts_result {
@@ -14238,6 +14360,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
&cmd_set_rxoffs,
&cmd_set_rxpkts,
&cmd_set_rxhdrs,
+ &cmd_create_pinned_rxpool,
&cmd_set_txflows,
&cmd_set_txpkts,
&cmd_set_txsplit,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f0f2b0758b..0ca263cc4e 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -867,6 +867,88 @@ Where eth[,ipv4]* represents a CSV list of values, without white space.
If the list of offsets is shorter than the list of segments,
zero offsets will be used for the remaining segments.
+create pinned-rxpool
+~~~~~~~~~~~~~~~~~~~~
+
+Create a pinned external-buffer Rx mempool for a buffer-split payload
+segment. Each mbuf in the pool is permanently bound to a fixed slot in
+a contiguous hugepage region allocated by testpmd. When the NIC
+performs a buffer-split receive, the payload DMA-writes directly into
+that hugepage memory without any extra copy from a normal mbuf.
+
+.. code-block:: none
+
+ testpmd> create pinned-rxpool (seg-idx) (count) (elt-size)
+
+Where:
+
+seg-idx
+ Index of the Rx split segment that will use the pinned pool.
+ 0 is the header segment (usually left as the default pool);
+ 1 is the first payload segment and is the typical target.
+
+count
+ Number of mbufs in the pool. Should be at least as large as the
+ number of Rx descriptors on all queues using this pool, plus a
+ safety margin (e.g. ``nb_rxd * nb_rxq * 2``).
+
+elt-size
+ Size of each pool element in bytes. This is the total slot stride,
+ including ``RTE_PKTMBUF_HEADROOM`` (default 128 B). For example,
+ to hold 1260-byte video payloads (SMPTE ST 2110-21 BPM size) with
+ a standard headroom, set ``elt-size`` to 1388 (= 128 + 1260).
+
+The pool is named according to testpmd's internal convention so that
+``rx_queue_setup()`` automatically selects it for segment ``seg-idx``
+when ``RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT`` is enabled.
+
+.. note::
+
+ VFIO or another IOMMU driver is required so that hugepage memory
+ has a valid IOVA. The backing hugepage allocation is not freed when
+ the port is stopped or the pool is re-created; restart testpmd to
+ reclaim it.
+
+**Example — zero-copy header/payload split for video streaming**
+
+This example mirrors the use case in the Media Transport Library (MTL)
+for SMPTE ST 2110-21 video reception. Headers land in the default
+pool; 1260-byte video payloads DMA directly into a pinned hugepage
+region without any copy. The pool holds enough slots for 4 K
+descriptors on 4 queues with headroom:
+
+.. code-block:: console
+
+ # Start testpmd with a default header pool (segment 0)
+ dpdk-testpmd -a 0000:31:00.0,enable-rx-timestamp=0 \
+ --mbuf-size=256 -- -i --rxq=4 --txq=4 --rxd=4096
+
+ # Inside testpmd:
+
+ # 1. Create the pinned payload pool for segment 1 (4*4096 mbufs,
+ # 1388 bytes each: 128 B headroom + 1260 B payload)
+ testpmd> create pinned-rxpool 1 32768 1388
+
+ # 2. Configure buffer split: segment 0 = UDP+lower headers,
+ # segment 1 = payload (length 0 means "rest of packet")
+ testpmd> set rxhdrs ipv4-udp
+ testpmd> set rxpkts 0,0
+
+ # 3. Enable buffer split on the port
+ testpmd> port config 0 rx_offload buffer_split on
+
+ # 4. Restart the queues so the new configuration takes effect
+ testpmd> stop
+ testpmd> port stop 0
+ testpmd> port start 0
+ testpmd> start
+
+After this sequence, each received UDP packet is split by the NIC:
+the header mbuf (chain head) comes from the default pool, and the
+payload mbuf (chain next) has its ``buf_addr`` pointing into the
+pinned hugepage region owned by the application — no copy, no
+callback, no new ethdev API.
+
set txpkts
~~~~~~~~~~
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply related
* [PATCH v4 4/5] net/iavf: disable runtime queue setup capability
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260703121952.1277387-1-dawid.wesierski@intel.com>
Remove the advertisement of RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP
and RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP capabilities from the
iavf VF driver.
Runtime queue setup on E810 VFs causes queue state corruption when
queues are dynamically reconfigured while the hardware rate limiter
is actively pacing TX queues. Queue configuration messages to the PF
via virtchnl can race with ongoing TX operations, leading to undefined
behavior.
By not advertising these capabilities, all queues are configured at
port start and remain stable throughout the port lifecycle.
Signed-off-by: Marek Kasiewicz <marek.kasiewicz@intel.com>
Signed-off-by: Dawid Wesierski <dawid.wesierski@intel.com>
---
doc/guides/nics/intel_vf.rst | 9 +++++++++
doc/guides/rel_notes/release_26_07.rst | 2 ++
drivers/net/intel/iavf/iavf.h | 1 +
drivers/net/intel/iavf/iavf_ethdev.c | 22 ++++++++++++++++++----
4 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst
index e010f852cf..86878330f2 100644
--- a/doc/guides/nics/intel_vf.rst
+++ b/doc/guides/nics/intel_vf.rst
@@ -131,6 +131,15 @@ IAVF PMD parameters
* ``segment``: Check number of mbuf segments does not exceed HW limits.
* ``offload``: Check for use of an unsupported offload flag.
+``no_runtime_queue_setup``
+ Runtime (post-start) Rx/Tx queue setup can race with the hardware Tx rate
+ limiter on E810 VFs and corrupt queue state.
+ It is advertised by default.
+ Applications that pace queues through the traffic manager can opt out
+ of advertising the runtime queue setup capability
+ by setting ``no_runtime_queue_setup`` to 1,
+ for example, ``-a 18:01.0,no_runtime_queue_setup=1``.
+
HW-Specific Notes For IAVF
^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 43b20b97e2..124e074a11 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -135,6 +135,8 @@ New Features
* Added support for transmitting LLDP packets based on mbuf packet type.
* Implemented AVX2 context descriptor transmit paths.
+ * Added ``no_runtime_queue_setup`` devarg to disable runtime queue setup
+ on devices that pace queues through the traffic manager.
* **Updated Intel ice driver.**
diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
index 4444602a30..146f02ea13 100644
--- a/drivers/net/intel/iavf/iavf.h
+++ b/drivers/net/intel/iavf/iavf.h
@@ -326,6 +326,7 @@ struct iavf_devargs {
int no_poll_on_link_down;
uint64_t mbuf_check;
int enable_ptype_lldp;
+ int no_runtime_queue_setup;
};
struct iavf_security_ctx;
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c b/drivers/net/intel/iavf/iavf_ethdev.c
index ec1ad02826..be733f9edf 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -46,6 +46,7 @@
#define IAVF_NO_POLL_ON_LINK_DOWN_ARG "no-poll-on-link-down"
#define IAVF_MBUF_CHECK_ARG "mbuf_check"
#define IAVF_ENABLE_PTYPE_LLDP_ARG "enable_ptype_lldp"
+#define IAVF_NO_RUNTIME_QUEUE_SETUP_ARG "no_runtime_queue_setup"
uint64_t iavf_timestamp_dynflag;
int iavf_timestamp_dynfield_offset = -1;
int rte_pmd_iavf_tx_lldp_dynfield_offset = -1;
@@ -59,6 +60,7 @@ static const char * const iavf_valid_args[] = {
IAVF_NO_POLL_ON_LINK_DOWN_ARG,
IAVF_MBUF_CHECK_ARG,
IAVF_ENABLE_PTYPE_LLDP_ARG,
+ IAVF_NO_RUNTIME_QUEUE_SETUP_ARG,
NULL
};
@@ -1160,9 +1162,15 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->reta_size = vf->vf_res->rss_lut_size;
dev_info->flow_type_rss_offloads = IAVF_RSS_OFFLOAD_ALL;
dev_info->max_mac_addrs = IAVF_NUM_MACADDR_MAX;
- dev_info->dev_capa =
- RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
- RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+ /*
+ * Runtime queue setup can race with the hardware Tx rate limiter on
+ * E810 VFs and corrupt queue state. Applications that pace queues via
+ * the traffic manager can opt out with no_runtime_queue_setup=1.
+ */
+ if (!adapter->devargs.no_runtime_queue_setup)
+ dev_info->dev_capa =
+ RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+ RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
dev_info->rx_offload_capa =
RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
@@ -2533,6 +2541,11 @@ static int iavf_parse_devargs(struct rte_eth_dev *dev)
if (ret)
goto bail;
+ ret = rte_kvargs_process(kvlist, IAVF_NO_RUNTIME_QUEUE_SETUP_ARG,
+ &parse_bool, &ad->devargs.no_runtime_queue_setup);
+ if (ret)
+ goto bail;
+
bail:
rte_kvargs_free(kvlist);
return ret;
@@ -3619,7 +3632,8 @@ bool is_iavf_supported(struct rte_eth_dev *dev)
RTE_PMD_REGISTER_PCI(net_iavf, rte_iavf_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_iavf, pci_id_iavf_map);
RTE_PMD_REGISTER_KMOD_DEP(net_iavf, "* igb_uio | vfio-pci");
-RTE_PMD_REGISTER_PARAM_STRING(net_iavf, "cap=dcf");
+RTE_PMD_REGISTER_PARAM_STRING(net_iavf, "cap=dcf"
+ IAVF_NO_RUNTIME_QUEUE_SETUP_ARG "=<0|1>");
RTE_LOG_REGISTER_SUFFIX(iavf_logtype_init, init, NOTICE);
RTE_LOG_REGISTER_SUFFIX(iavf_logtype_driver, driver, NOTICE);
#ifdef RTE_ETHDEV_DEBUG_RX
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply related
* [PATCH v4 3/5] net/ice: add scheduler rate-limiter burst size devarg
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260703121952.1277387-1-dawid.wesierski@intel.com>
The E810 Tx scheduler uses a token bucket algorithm where the burst
size controls the maximum bytes sent in a single burst before the
rate limiter throttles. The hardware default of 15 KB allows
micro-bursts of ~10 max-size frames, which violates tight
inter-packet spacing requirements in time-sensitive networking
applications such as SMPTE ST 2110-21 narrow-sender compliance.
Add a "rl_burst_size" device argument that lets the application lower
the scheduler rate-limiter burst size (for example to 2 KB) to force
near-constant-rate output matching the configured shaper profile.
The burst size is a global scheduler resource, so the override is
applied once at probe time and only when the user explicitly requests
it; the hardware default is left unchanged otherwise.
Signed-off-by: Marek Kasiewicz <marek.kasiewicz@intel.com>
Signed-off-by: Dawid Wesierski <dawid.wesierski@intel.com>
---
doc/guides/nics/ice.rst | 12 +++++++
doc/guides/rel_notes/release_26_07.rst | 5 +++
drivers/net/intel/ice/ice_ethdev.c | 46 ++++++++++++++++++++++++++
drivers/net/intel/ice/ice_ethdev.h | 1 +
4 files changed, 64 insertions(+)
diff --git a/doc/guides/nics/ice.rst b/doc/guides/nics/ice.rst
index 8251416918..6c2063d47e 100644
--- a/doc/guides/nics/ice.rst
+++ b/doc/guides/nics/ice.rst
@@ -158,6 +158,18 @@ Runtime Configuration
-a 80:00.0,source-prune=1
+- ``Scheduler rate-limiter burst size`` (default ``0``)
+
+ The hardware Tx scheduler uses a default rate-limiter burst size that favours
+ throughput. Time-sensitive applications can lower this value to reduce Tx
+ latency jitter at the cost of throughput by setting the ``rl_burst_size``
+ devargs parameter, in bytes. Values that are out of range are rejected.
+ A value of ``0`` (the default) keeps the hardware default.
+
+ For example::
+
+ -a 80:00.0,rl_burst_size=2048
+
- ``Protocol extraction for per queue``
Configure the RX queues to do protocol extraction into mbuf for protocol
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 0b1cac3e0d..43b20b97e2 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -136,6 +136,11 @@ New Features
* Added support for transmitting LLDP packets based on mbuf packet type.
* Implemented AVX2 context descriptor transmit paths.
+* **Updated Intel ice driver.**
+
+ * Added ``rl_burst_size`` devarg to configure the scheduler rate-limiter
+ burst size, reducing Tx latency jitter for time-sensitive traffic.
+
* **Updated NVIDIA mlx5 ethernet driver.**
* Added support for selective Rx in scalar SPRQ Rx path.
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index ad9c49b339..465cf07383 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -41,6 +41,7 @@
#define ICE_DDP_FILENAME_ARG "ddp_pkg_file"
#define ICE_DDP_LOAD_SCHED_ARG "ddp_load_sched_topo"
#define ICE_TM_LEVELS_ARG "tm_sched_levels"
+#define ICE_RL_BURST_SIZE_ARG "rl_burst_size"
#define ICE_SOURCE_PRUNE_ARG "source-prune"
#define ICE_LINK_STATE_ON_CLOSE "link_state_on_close"
@@ -59,6 +60,7 @@ static const char * const ice_valid_args[] = {
ICE_DDP_FILENAME_ARG,
ICE_DDP_LOAD_SCHED_ARG,
ICE_TM_LEVELS_ARG,
+ ICE_RL_BURST_SIZE_ARG,
ICE_SOURCE_PRUNE_ARG,
ICE_LINK_STATE_ON_CLOSE,
NULL
@@ -2147,6 +2149,29 @@ parse_u64(const char *key, const char *value, void *args)
return 0;
}
+static int
+parse_u32(const char *key, const char *value, void *args)
+{
+ uint32_t *num = args;
+ unsigned long tmp;
+ char *endptr;
+
+ errno = 0;
+ tmp = strtoul(value, &endptr, 0);
+ if (errno != 0 || endptr == value || *endptr != '\0') {
+ PMD_DRV_LOG(WARNING, "%s: \"%s\" is not a valid u32", key, value);
+ return -1;
+ }
+ if (tmp > UINT32_MAX) {
+ PMD_DRV_LOG(WARNING, "%s: value \"%s\" is out of range", key, value);
+ return -1;
+ }
+
+ *num = (uint32_t)tmp;
+
+ return 0;
+}
+
static int
parse_tx_sched_levels(const char *key, const char *value, void *args)
{
@@ -2448,6 +2473,11 @@ static int ice_parse_devargs(struct rte_eth_dev *dev)
if (ret)
goto bail;
+ ret = rte_kvargs_process(kvlist, ICE_RL_BURST_SIZE_ARG,
+ &parse_u32, &ad->devargs.rl_burst_size);
+ if (ret)
+ goto bail;
+
ret = rte_kvargs_process(kvlist, ICE_SOURCE_PRUNE_ARG,
&parse_bool, &ad->devargs.source_prune);
if (ret)
@@ -2662,6 +2692,21 @@ ice_dev_init(struct rte_eth_dev *dev)
return -EINVAL;
}
+ /*
+ * Override the hardware default scheduler rate-limiter burst size only
+ * when the user explicitly requests it. A smaller burst reduces Tx
+ * latency jitter for time-sensitive traffic at the cost of throughput,
+ * so it must not change for every port. ice_cfg_rl_burst_size()
+ * validates the value against the hardware-allowed range.
+ */
+ if (ad->devargs.rl_burst_size != 0 &&
+ ice_cfg_rl_burst_size(hw, ad->devargs.rl_burst_size) != 0) {
+ PMD_INIT_LOG(ERR, "Invalid rl_burst_size %u bytes",
+ ad->devargs.rl_burst_size);
+ ice_deinit_hw(hw);
+ return -EINVAL;
+ }
+
#ifndef RTE_EXEC_ENV_WINDOWS
use_dsn = false;
dsn = 0;
@@ -7713,6 +7758,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_ice,
ICE_DDP_FILENAME_ARG "=</path/to/file>"
ICE_DDP_LOAD_SCHED_ARG "=<0|1>"
ICE_TM_LEVELS_ARG "=<N>"
+ ICE_RL_BURST_SIZE_ARG "=<N>"
ICE_SOURCE_PRUNE_ARG "=<0|1>"
ICE_RX_LOW_LATENCY_ARG "=<0|1>"
ICE_LINK_STATE_ON_CLOSE "=<down|up|initial>");
diff --git a/drivers/net/intel/ice/ice_ethdev.h b/drivers/net/intel/ice/ice_ethdev.h
index 20e8a13fe9..0a9d75b9cd 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -631,6 +631,7 @@ struct ice_devargs {
uint8_t ddp_load_sched;
uint8_t tm_exposed_levels;
uint8_t source_prune;
+ uint32_t rl_burst_size;
int link_state_on_close;
int xtr_field_offs;
uint8_t xtr_flag_offs[PROTO_XTR_MAX];
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply related
* [PATCH v4 2/5] net/iavf: allow runtime queue rate limit configuration
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260703121952.1277387-1-dawid.wesierski@intel.com>
Allow per-queue bandwidth rate limiting to be configured without
stopping the port when only a single TC node and single QoS element
are involved. This enables dynamic session management where individual
queue pacing rates can be changed while other queues continue
transmitting.
Also fix the queue ID assignment in the bandwidth configuration to
use the actual TM node ID rather than a sequential counter index, and
only mark the TM hierarchy as committed when the port is stopped to
permit subsequent reconfiguration.
Signed-off-by: Marek Kasiewicz <marek.kasiewicz@intel.com>
Signed-off-by: Dawid Wesierski <dawid.wesierski@intel.com>
---
drivers/net/intel/iavf/iavf_tm.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_tm.c b/drivers/net/intel/iavf/iavf_tm.c
index 1cf7bfb106..e3492ec491 100644
--- a/drivers/net/intel/iavf/iavf_tm.c
+++ b/drivers/net/intel/iavf/iavf_tm.c
@@ -804,19 +804,25 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
int index = 0, node_committed = 0;
int i, ret_val = IAVF_SUCCESS;
- /* check if port is stopped */
- if (adapter->stopped != 1) {
- PMD_DRV_LOG(ERR, "Please stop port first");
- ret_val = IAVF_ERR_NOT_READY;
- goto err;
- }
-
if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS)) {
PMD_DRV_LOG(ERR, "VF queue tc mapping is not supported");
ret_val = IAVF_NOT_SUPPORTED;
goto fail_clear;
}
+ /*
+ * Allow reconfiguration on a running port only when a single queue is
+ * involved (single TC node and single QoS element); otherwise the port
+ * must be stopped first. qos_cap is valid here because the
+ * VIRTCHNL_VF_OFFLOAD_QOS capability was checked above.
+ */
+ if ((vf->tm_conf.nb_tc_node != 1 || vf->qos_cap->num_elem != 1) &&
+ adapter->stopped != 1) {
+ PMD_DRV_LOG(ERR, "Please stop port first");
+ ret_val = IAVF_ERR_NOT_READY;
+ goto err;
+ }
+
/* check if all TC nodes are set with VF vsi */
if (vf->tm_conf.nb_tc_node != vf->qos_cap->num_elem) {
PMD_DRV_LOG(ERR, "Does not set VF vsi nodes to all TCs");
@@ -856,7 +862,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
q_tc_mapping->tc[tm_node->tc].req.queue_count++;
if (tm_node->shaper_profile) {
- q_bw->cfg[node_committed].queue_id = node_committed;
+ q_bw->cfg[node_committed].queue_id = tm_node->id;
q_bw->cfg[node_committed].shaper.peak =
tm_node->shaper_profile->profile.peak.rate /
1000 * IAVF_BITS_PER_BYTE;
@@ -900,7 +906,8 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
goto fail_clear;
vf->qtc_map = qtc_map;
- vf->tm_conf.committed = true;
+ if (adapter->stopped == 1)
+ vf->tm_conf.committed = true;
return ret_val;
fail_clear:
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply related
* [PATCH v4 1/5] net/iavf: increase max ring descriptors to hardware limit
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260703121952.1277387-1-dawid.wesierski@intel.com>
The Intel E810 hardware supports up to 8160 (8K - 32) descriptors per
TX/RX ring, but IAVF_MAX_RING_DESC caps it at 4096. Applications that
need deep descriptor rings for hardware rate-limited pacing (e.g.,
ST2110 video with thousands of packets per frame) cannot queue enough
packets before the pacing epoch begins.
Increase IAVF_MAX_RING_DESC to the hardware maximum of 8160 to allow
full utilization of the ring depth on E810 VFs.
Signed-off-by: Marek Kasiewicz <marek.kasiewicz@intel.com>
Signed-off-by: Dawid Wesierski <dawid.wesierski@intel.com>
---
.mailmap | 2 ++
drivers/net/intel/iavf/iavf_rxtx.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.mailmap b/.mailmap
index 4001e5fb0e..d7b175de2a 100644
--- a/.mailmap
+++ b/.mailmap
@@ -366,6 +366,7 @@ David Zeng <zengxhsh@cn.ibm.com>
Davide Caratti <dcaratti@redhat.com>
Dawid Gorecki <dgr@semihalf.com>
Dawid Jurczak <dawid_jurek@vp.pl>
+Dawid Wesierski <dawid.wesierski@intel.com>
Dawid Zielinski <dawid.zielinski@intel.com>
Dawid Łukwiński <dawid.lukwinski@intel.com>
Daxue Gao <daxuex.gao@intel.com>
@@ -1014,6 +1015,7 @@ Marcin Wilk <marcin.wilk@caviumnetworks.com>
Marcin Wojtas <mw@semihalf.com>
Marcin Zapolski <marcinx.a.zapolski@intel.com>
Marco Varlese <mvarlese@suse.de>
+Marek Kasiewicz <marek.kasiewicz@intel.com>
Marek Mical <marekx.mical@intel.com>
Marek Zalfresso-jundzillo <marekx.zalfresso-jundzillo@intel.com>
Maria Lingemark <maria.lingemark@ericsson.com>
diff --git a/drivers/net/intel/iavf/iavf_rxtx.h b/drivers/net/intel/iavf/iavf_rxtx.h
index 8449236d4d..22ea415f44 100644
--- a/drivers/net/intel/iavf/iavf_rxtx.h
+++ b/drivers/net/intel/iavf/iavf_rxtx.h
@@ -16,7 +16,7 @@
/* In QLEN must be whole number of 32 descriptors. */
#define IAVF_ALIGN_RING_DESC 32
#define IAVF_MIN_RING_DESC 64
-#define IAVF_MAX_RING_DESC 4096
+#define IAVF_MAX_RING_DESC (8192 - 32)
#define IAVF_DMA_MEM_ALIGN 4096
/* Base address of the HW descriptor ring should be 128B aligned. */
#define IAVF_RING_BASE_ALIGN 128
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply related
* [PATCH v4 0/5] Intel network drivers enhancements
From: Dawid Wesierski @ 2026-07-03 12:19 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, marek.kasiewicz,
Dawid Wesierski
In-Reply-To: <20260630120657.1046588-1-dawid.wesierski@intel.com>
This series collects Intel E810 iavf and ice driver enhancements developed
for the Media Transport Library (MTL) to support high-performance SMPTE
ST 2110 media streaming workflows.
The header/payload split use case is served by the standard DPDK
buffer-split offload combined with pinned external-buffer mempools
(RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF): by pinning mbufs to contiguous
hugepages, the NIC DMAs RTP payloads directly into application-owned
memory. A concrete configuration example and the 'create pinned-rxpool'
testpmd command that serves as a reference implementation are documented
in the testpmd user guide (patch 5/5).
In this series:
- iavf maximum ring descriptor count raised to the E810 hardware limit.
- iavf queue rate limit reconfiguration allowed at runtime.
- Added opt-in "rl_burst_size" ice devarg for tighter packet spacing
(jitter reduction).
- Added opt-in "no_runtime_queue_setup" iavf devarg to restore strict
initialization semantics when required.
v3 -> v4:
- Dropped the ice PTP documentation patch entirely. Applications that
need a hardware Rx timestamp on all traffic (not just IEEE 1588
packets) already have RTE_ETH_RX_OFFLOAD_TIMESTAMP available today;
this is an existing, generic offload and does not need a dedicated
patch to point it out. The datapath change that misidentified regular
traffic as PTP (flagged by Bruce Richardson) is also dropped with it.
- Set the whole series author to Dawid Wesierski.
- Rebased onto latest main.
v2 -> v3:
- Dropped the ethdev and net/intel "header-split mbuf callback" API in
favour of the upstream-preferred pinned-external-buffer workflow, now
demonstrated in testpmd (patch 5).
- Fixed iavf error propagation and committed-state logic
(Stephen Hemminger).
- Converted the ice scheduler burst reduction and iavf runtime-config
disabling into opt-in devargs to preserve default behaviour.
- Updated documentation, commit messages, and .mailmap.
Dawid Wesierski (5):
net/iavf: increase max ring descriptors to hardware limit
net/iavf: allow runtime queue rate limit configuration
net/ice: add scheduler rate-limiter burst size devarg
net/iavf: disable runtime queue setup capability
app/testpmd: add pinned external-buffer Rx pool command
.mailmap | 2 +
app/test-pmd/cmdline.c | 123 ++++++++++++++++++++
doc/guides/nics/ice.rst | 12 ++
doc/guides/nics/intel_vf.rst | 9 ++
doc/guides/rel_notes/release_26_07.rst | 7 ++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 82 +++++++++++++
drivers/net/intel/iavf/iavf.h | 1 +
drivers/net/intel/iavf/iavf_ethdev.c | 22 +++-
drivers/net/intel/iavf/iavf_rxtx.h | 2 +-
drivers/net/intel/iavf/iavf_tm.c | 25 ++--
drivers/net/intel/ice/ice_ethdev.c | 46 ++++++++
drivers/net/intel/ice/ice_ethdev.h | 1 +
12 files changed, 318 insertions(+), 14 deletions(-)
--
2.47.3
---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
^ permalink raw reply
* RE: [PATCH] test/bpf: remove validation tests from CI
From: Marat Khalili @ 2026-07-03 11:39 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev@dpdk.org, Konstantin Ananyev
In-Reply-To: <uL3Gmts1SCa1M0sJvOuIOQ@monjalon.net>
> > I think I know the issue, it's tmpfs exhaustion. After some recent changes each
> > test consumes 25MB in the --file-prefix directory independently, easily driving
> > small VMs out of space. My ~30 new tests were the last drop for the CI.
>
> I don't whether it would improve, but it is a lot of tests,
> could you take this opportunity to group all BPF validation tests
> in a single registered test?
> At least it would reduce the noise in test reports.
TBH wasting many GBs of /run for no reason is a problem anyway.
I had problems with running DPDK tests in small containers after
--file-prefix became test-specific, but did not connect the dots.
I will try to merge new tests into one too if it helps test reports
(hopefully they won't exceed fast test timeout as a result).
^ permalink raw reply
* Re: [PATCH] test/bpf: remove validation tests from CI
From: Thomas Monjalon @ 2026-07-03 11:32 UTC (permalink / raw)
To: Marat Khalili; +Cc: dev@dpdk.org, Konstantin Ananyev
In-Reply-To: <2751fd1fa6d648a9b7f95797f13ef28b@huawei.com>
03/07/2026 10:48, Marat Khalili:
> > The new tests for BPF validation are triggering a strange issue
> > in GitHub Action: the last tests are killed by signal 7 SIGBUS.
> >
> > The series fixing a lot of BPF issues was merged
> > but the related test has to be removed from the fast tests suite
> > which runs in some CI jobs.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>
> I think I know the issue, it's tmpfs exhaustion. After some recent changes each
> test consumes 25MB in the --file-prefix directory independently, easily driving
> small VMs out of space. My ~30 new tests were the last drop for the CI.
I don't whether it would improve, but it is a lot of tests,
could you take this opportunity to group all BPF validation tests
in a single registered test?
At least it would reduce the noise in test reports.
> I will try to prepare a fix today, of course please do everything that's
> needed for the CI stability meanwhile.
I've merged this fix (fixed) already.
Thanks for working on it.
^ permalink raw reply
* [PATCH] devtools: support local opencode agent for patch review
From: datshan @ 2026-07-03 9:19 UTC (permalink / raw)
To: thomas, stephen; +Cc: aconole, dev
From: Chengwen Feng <fengchengwen@huawei.com>
Currently review-patch.py only supports cloud AI providers
(Anthropic, OpenAI, xAI, Google) via REST API, requiring API keys.
Add a --via option that invokes the locally installed opencode CLI as
the review runner instead of making HTTP calls. opencode reads
AGENTS.md from the DPDK project directory automatically, needing no
configuration beyond opencode on PATH.
The --via and -p/--provider options are independent -- via routes to
the local agent mode while -p continues to use the cloud API path.
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
devtools/ai/review-patch.py | 223 ++++++++++++++++++++++++++----------
1 file changed, 162 insertions(+), 61 deletions(-)
diff --git a/devtools/ai/review-patch.py b/devtools/ai/review-patch.py
index 52601ac156..a05c1e81df 100755
--- a/devtools/ai/review-patch.py
+++ b/devtools/ai/review-patch.py
@@ -3,9 +3,10 @@
# Copyright(c) 2026 Stephen Hemminger
"""
-Review DPDK patches using AI providers.
+Review DPDK patches using AI providers or a local agent tool.
Supported providers: Anthropic Claude, OpenAI ChatGPT, xAI Grok, Google Gemini
+Supported agent: OpenCode (--via opencode)
"""
import argparse
@@ -551,6 +552,111 @@ def build_google_request(
}
+def _call_opencode(
+ model: str,
+ max_tokens: int,
+ system_prompt: str,
+ patch_content: str,
+ patch_name: str,
+ output_format: str = "text",
+ verbose: bool = False,
+ timeout: int = 300,
+) -> tuple[str, TokenUsage]:
+ """Call local opencode CLI for review."""
+ import tempfile
+
+ format_instruction = FORMAT_INSTRUCTIONS.get(output_format, "")
+ user_prompt = (
+ f"Review the attached DPDK patch file '{patch_name}'.\n\n"
+ f"Focus on correctness bugs, C coding style, API requirements, "
+ f"and other guideline violations. "
+ f"Commit message format and SPDX/copyright are checked by "
+ f"checkpatches.sh — do NOT flag those.\n\n"
+ f"{format_instruction}"
+ )
+
+ with tempfile.NamedTemporaryFile(
+ mode="w", suffix=".patch", delete=False, prefix="review_"
+ ) as f:
+ f.write(patch_content)
+ patch_temp = f.name
+
+ try:
+ full_message = (
+ f"{system_prompt}\n\n{user_prompt}"
+ )
+
+ cmd = [
+ "opencode", "run", "--format", "json",
+ "--dir", str(Path(__file__).resolve().parent.parent.parent),
+ "--file", patch_temp,
+ ]
+ if model:
+ cmd.extend(["--model", model])
+ if verbose:
+ cmd.append("--print-logs")
+ cmd.append("--")
+ cmd.append(full_message)
+
+ if verbose:
+ print(f"Running: {' '.join(cmd[:-1])} '...'", file=sys.stderr)
+
+ try:
+ result = subprocess.run(
+ cmd,
+ capture_output=True,
+ text=True,
+ timeout=timeout,
+ )
+ except FileNotFoundError:
+ error("opencode not found. Install from https://opencode.ai")
+
+ if result.returncode != 0:
+ error(
+ f"opencode exited with code {result.returncode}: "
+ f"{result.stderr[:500]}"
+ )
+
+ finally:
+ os.unlink(patch_temp)
+
+ text_parts = []
+ usage = TokenUsage()
+ steps = 0
+
+ for line in result.stdout.splitlines():
+ stripped = line.strip()
+ if not stripped:
+ continue
+ try:
+ event = json.loads(stripped)
+ except json.JSONDecodeError:
+ continue
+
+ event_type = event.get("type", "")
+ if event_type == "text":
+ part_text = event.get("part", {}).get("text", "")
+ if part_text:
+ text_parts.append(part_text)
+ elif event_type == "step_finish":
+ steps += 1
+ tokens = event.get("part", {}).get("tokens", {})
+ if tokens:
+ usage.input_tokens += tokens.get("input", 0)
+ usage.output_tokens += tokens.get("output", 0)
+ cache = tokens.get("cache", {})
+ usage.cache_creation_tokens += cache.get("write", 0)
+ usage.cache_read_tokens += cache.get("read", 0)
+
+ usage.api_calls = 1 if steps > 0 else 0
+ review_text = "\n".join(text_parts)
+
+ if not review_text:
+ error(f"No review text received from opencode")
+
+ return review_text, usage
+
+
def call_api(
provider: str,
api_key: str,
@@ -740,6 +846,7 @@ def main() -> None:
Examples:
%(prog)s patch.patch # Review with default settings
%(prog)s -p openai my-patch.patch # Use OpenAI ChatGPT
+ %(prog)s --via opencode my-patch.patch # Use local opencode agent
%(prog)s -f markdown patch.patch # Output as Markdown
%(prog)s -f json -o review.json patch.patch # Save JSON to file
%(prog)s -f html -o review.html patch.patch # Save HTML to file
@@ -786,7 +893,13 @@ def main() -> None:
"--provider",
choices=PROVIDERS.keys(),
default="anthropic",
- help="AI provider (default: anthropic)",
+ help="Cloud AI provider (default: anthropic)",
+ )
+ parser.add_argument(
+ "--via",
+ choices=["opencode"],
+ default=None,
+ help="Use a local agent tool instead of a cloud API (e.g. --via opencode)",
)
parser.add_argument(
"-a",
@@ -926,14 +1039,19 @@ def main() -> None:
if not args.patch_file:
parser.error("patch_file is required")
- # Get provider config
- config = PROVIDERS[args.provider]
- model = args.model or config["default_model"]
-
- # Get API key
- api_key = os.environ.get(config["env_var"])
- if not api_key:
- error(f"{config['env_var']} environment variable not set")
+ # Get provider config or set up local agent runner
+ via = args.via
+ if via:
+ model = args.model or ""
+ api_key = ""
+ provider_name = "OpenCode"
+ else:
+ config = PROVIDERS[args.provider]
+ model = args.model or config["default_model"]
+ api_key = os.environ.get(config["env_var"])
+ if not api_key:
+ error(f"{config['env_var']} environment variable not set")
+ provider_name = config["name"]
# Validate files
agents_path = Path(args.agents)
@@ -971,13 +1089,30 @@ def main() -> None:
patch_content = patch_path.read_text(encoding="utf-8", errors="replace")
patch_name = patch_path.name
- # Determine max tokens for this provider
- max_input_tokens = args.max_tokens or PROVIDER_INPUT_LIMITS.get(
- args.provider, 100000
- )
+ # Dispatch to agent or provider
+ def _run_review(patch_body: str, patch_label: str) -> tuple[str, TokenUsage]:
+ if via:
+ return _call_opencode(
+ model, args.tokens, system_prompt,
+ patch_body, patch_label,
+ args.output_format, args.verbose, args.timeout,
+ )
+ return call_api(
+ args.provider, api_key, model, args.tokens,
+ system_prompt, agents_content,
+ patch_body, patch_label,
+ args.output_format, args.verbose, args.timeout,
+ )
- # Estimate token count
- estimated_tokens = estimate_tokens(patch_content + agents_content)
+ # Determine max tokens (cloud API only)
+ max_input_tokens = 0
+ if via:
+ estimated_tokens = 1
+ else:
+ max_input_tokens = args.max_tokens or PROVIDER_INPUT_LIMITS.get(
+ args.provider, 100000
+ )
+ estimated_tokens = estimate_tokens(patch_content + agents_content)
# Accumulate token usage across all API calls
total_usage = TokenUsage()
@@ -1039,19 +1174,7 @@ def main() -> None:
patch_label = f"Patch {i}/{total_patches}"
print(f"\nReviewing {patch_label}...", file=sys.stderr)
- review_text, call_usage = call_api(
- args.provider,
- api_key,
- model,
- args.tokens,
- system_prompt,
- agents_content,
- patch,
- f"{patch_name} ({patch_label})",
- args.output_format,
- args.verbose,
- args.timeout,
- )
+ review_text, call_usage = _run_review(patch, f"{patch_name} ({patch_label})")
total_usage.add(call_usage)
all_reviews.append((patch_label, review_text))
@@ -1063,10 +1186,10 @@ def main() -> None:
# Skip the normal API call
estimated_tokens = 0 # Bypass size check since we've already processed
- # Check if content is too large
+ # Check if content is too large (cloud API only)
is_large = estimated_tokens > max_input_tokens
- if is_large:
+ if is_large and not via:
print(
f"Warning: Estimated {estimated_tokens:,} tokens exceeds limit of "
f"{max_input_tokens:,}",
@@ -1109,19 +1232,7 @@ def main() -> None:
chunk_label = f"Chunk {chunk_num}/{total_chunks}"
print(f"Reviewing {chunk_label}...", file=sys.stderr)
- review_text, call_usage = call_api(
- args.provider,
- api_key,
- model,
- args.tokens,
- system_prompt,
- agents_content,
- chunk,
- f"{patch_name} ({chunk_label})",
- args.output_format,
- args.verbose,
- args.timeout,
- )
+ review_text, call_usage = _run_review(chunk, f"{patch_name} ({chunk_label})")
total_usage.add(call_usage)
all_reviews.append((chunk_label, review_text))
@@ -1135,7 +1246,10 @@ def main() -> None:
if args.verbose:
print("=== Request ===", file=sys.stderr)
- print(f"Provider: {args.provider}", file=sys.stderr)
+ if via:
+ print(f"Runner: {args.via}", file=sys.stderr)
+ else:
+ print(f"Provider: {args.provider}", file=sys.stderr)
print(f"Model: {model}", file=sys.stderr)
print(f"Review date: {review_date}", file=sys.stderr)
if args.release:
@@ -1162,26 +1276,13 @@ def main() -> None:
# Call API (unless already processed via chunks/split)
if estimated_tokens > 0: # Not already processed
- review_text, call_usage = call_api(
- args.provider,
- api_key,
- model,
- args.tokens,
- system_prompt,
- agents_content,
- patch_content,
- patch_name,
- args.output_format,
- args.verbose,
- args.timeout,
- )
+ review_text, call_usage = _run_review(patch_content, patch_name)
total_usage.add(call_usage)
if not review_text:
- error(f"No response received from {args.provider}")
+ error(f"No response received from {provider_name}")
# Format output based on requested format
- provider_name = config["name"]
if args.output_format == "json":
# For JSON, try to parse and add metadata
@@ -1260,7 +1361,7 @@ def main() -> None:
print_token_summary(
total_usage,
- args.provider,
+ args.via or args.provider,
model,
args.show_tokens or args.verbose,
)
--
2.54.0
^ permalink raw reply related
* RE: [PATCH] test/bpf: remove validation tests from CI
From: Marat Khalili @ 2026-07-03 8:48 UTC (permalink / raw)
To: Thomas Monjalon, dev@dpdk.org; +Cc: Konstantin Ananyev
In-Reply-To: <20260703022738.2574548-1-thomas@monjalon.net>
> The new tests for BPF validation are triggering a strange issue
> in GitHub Action: the last tests are killed by signal 7 SIGBUS.
>
> The series fixing a lot of BPF issues was merged
> but the related test has to be removed from the fast tests suite
> which runs in some CI jobs.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
I think I know the issue, it's tmpfs exhaustion. After some recent changes each
test consumes 25MB in the --file-prefix directory independently, easily driving
small VMs out of space. My ~30 new tests were the last drop for the CI.
I will try to prepare a fix today, of course please do everything that's
needed for the CI stability meanwhile.
^ permalink raw reply
* [PATCH 2/2] net/iavf: fix leak of queue to traffic class mapping data
From: Bruce Richardson @ 2026-07-03 8:33 UTC (permalink / raw)
To: dev; +Cc: Bruce Richardson, stable, Vladimir Medvedkin, Ting Xu, Qi Zhang
In-Reply-To: <20260703083335.4058936-1-bruce.richardson@intel.com>
On iavf TM hierarchy commit, the queue to traffic class mapping is
generated and stored in a pointer from the VF structure. However, that
data is never later freed. The data is also unnecessarily allocated from
hugepage memory.
Fix these issues by replacing rte_zmalloc with calloc, and then
appropriately freeing the memory at a) uninit of the device, b) at
failure of apply of the new settings and c) replacement of old data by
new.
Fixes: 3fd32df381f8 ("net/iavf: check Tx packet with correct UP and queue")
Cc: stable@dpdk.org
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
drivers/net/intel/iavf/iavf_ethdev.c | 2 ++
drivers/net/intel/iavf/iavf_tm.c | 11 ++++++++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c b/drivers/net/intel/iavf/iavf_ethdev.c
index 80e740ef29..1cd8c88384 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -2755,6 +2755,8 @@ iavf_uninit_vf(struct rte_eth_dev *dev)
rte_free(vf->qos_cap);
vf->qos_cap = NULL;
+ free(vf->qtc_map);
+ vf->qtc_map = NULL;
rte_free(vf->rss_lut);
vf->rss_lut = NULL;
diff --git a/drivers/net/intel/iavf/iavf_tm.c b/drivers/net/intel/iavf/iavf_tm.c
index cc5c86b4ce..0f39da232d 100644
--- a/drivers/net/intel/iavf/iavf_tm.c
+++ b/drivers/net/intel/iavf/iavf_tm.c
@@ -96,6 +96,9 @@ iavf_tm_conf_uninit(struct rte_eth_dev *dev)
shaper_profile, node);
rte_free(shaper_profile);
}
+
+ free(vf->qtc_map);
+ vf->qtc_map = NULL;
}
static inline struct iavf_tm_node *
@@ -800,7 +803,8 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
struct virtchnl_queues_bw_cfg *q_bw = NULL;
struct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;
struct iavf_tm_node *tm_node;
- struct iavf_qtc_map *qtc_map;
+ struct iavf_qtc_map *qtc_map = NULL;
+ struct iavf_qtc_map *old_qtc_map = vf->qtc_map; /* to free memory if new map assigned */
uint16_t size, size_q;
int index = 0, node_committed = 0;
int i, ret_val = IAVF_SUCCESS;
@@ -888,8 +892,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
goto fail_clear;
/* store the queue TC mapping info */
- qtc_map = rte_zmalloc("qtc_map",
- sizeof(struct iavf_qtc_map) * q_tc_mapping->num_tc, 0);
+ qtc_map = calloc(q_tc_mapping->num_tc, sizeof(struct iavf_qtc_map));
if (!qtc_map) {
ret_val = IAVF_ERR_NO_MEMORY;
goto fail_clear;
@@ -909,6 +912,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
goto fail_clear;
vf->qtc_map = qtc_map;
+ free(old_qtc_map);
if (adapter->stopped == 1)
vf->tm_conf.committed = true;
free(q_bw);
@@ -924,5 +928,6 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
err:
free(q_bw);
free(q_tc_mapping);
+ free(qtc_map);
return ret_val;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 1/2] net/iavf: fix local memory leaks in TM hierarchy commit
From: Bruce Richardson @ 2026-07-03 8:33 UTC (permalink / raw)
To: dev
Cc: Bruce Richardson, stable, Vladimir Medvedkin, Ting Xu, Qi Zhang,
Qiming Yang, Wenjun Wu
The iavf_hierachy_commit function uses a number of temporary variables,
which, though small, are still leaked at function end. Clean this up by
freeing them before the function returns. Since these are not variables
that need to be in hugepage memory, also switch from using rte_zmalloc
to calloc.
Fixes: 44d0a720a538 ("net/iavf: query QoS capabilities and set queue TC mapping")
Fixes: 5779a8894d15 ("net/iavf: support queue rate limit configuration")
Cc: stable@dpdk.org
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
drivers/net/intel/iavf/iavf_tm.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_tm.c b/drivers/net/intel/iavf/iavf_tm.c
index e3492ec491..cc5c86b4ce 100644
--- a/drivers/net/intel/iavf/iavf_tm.c
+++ b/drivers/net/intel/iavf/iavf_tm.c
@@ -2,6 +2,7 @@
* Copyright(c) 2010-2017 Intel Corporation
*/
#include <rte_tm_driver.h>
+#include <stdlib.h>
#include "iavf.h"
@@ -795,8 +796,8 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct iavf_adapter *adapter =
IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
- struct virtchnl_queue_tc_mapping *q_tc_mapping;
- struct virtchnl_queues_bw_cfg *q_bw;
+ struct virtchnl_queue_tc_mapping *q_tc_mapping = NULL;
+ struct virtchnl_queues_bw_cfg *q_bw = NULL;
struct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;
struct iavf_tm_node *tm_node;
struct iavf_qtc_map *qtc_map;
@@ -832,7 +833,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
size = sizeof(*q_tc_mapping) + sizeof(q_tc_mapping->tc[0]) *
(vf->qos_cap->num_elem - 1);
- q_tc_mapping = rte_zmalloc("q_tc", size, 0);
+ q_tc_mapping = calloc(1, size);
if (!q_tc_mapping) {
ret_val = IAVF_ERR_NO_MEMORY;
goto fail_clear;
@@ -840,7 +841,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
size_q = sizeof(*q_bw) + sizeof(q_bw->cfg[0]) *
(vf->num_queue_pairs - 1);
- q_bw = rte_zmalloc("q_bw", size_q, 0);
+ q_bw = calloc(1, size_q);
if (!q_bw) {
ret_val = IAVF_ERR_NO_MEMORY;
goto fail_clear;
@@ -889,8 +890,10 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
/* store the queue TC mapping info */
qtc_map = rte_zmalloc("qtc_map",
sizeof(struct iavf_qtc_map) * q_tc_mapping->num_tc, 0);
- if (!qtc_map)
- return IAVF_ERR_NO_MEMORY;
+ if (!qtc_map) {
+ ret_val = IAVF_ERR_NO_MEMORY;
+ goto fail_clear;
+ }
for (i = 0; i < q_tc_mapping->num_tc; i++) {
q_tc_mapping->tc[i].req.start_queue_id = index;
@@ -908,6 +911,8 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
vf->qtc_map = qtc_map;
if (adapter->stopped == 1)
vf->tm_conf.committed = true;
+ free(q_bw);
+ free(q_tc_mapping);
return ret_val;
fail_clear:
@@ -917,5 +922,7 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
iavf_tm_conf_init(dev);
}
err:
+ free(q_bw);
+ free(q_tc_mapping);
return ret_val;
}
--
2.53.0
^ permalink raw reply related
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