* [PATCH v2 07/22] drivers: add support for devargs skip size
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
From: Kiran Kumar K <kirankumark@marvell.com>
Adding support for devargs skip_size to cnxk driver.
This allows users to specify the number of bytes to skip in the packet
parsing before L2.
Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
---
Changes in v2: No change.
doc/guides/nics/cnxk.rst | 19 +++++++-
drivers/common/cnxk/roc_mbox.h | 12 ++++-
drivers/common/cnxk/roc_nix.h | 14 ++----
drivers/common/cnxk/roc_nix_ops.c | 46 +++++++++++++++++--
drivers/common/cnxk/roc_npc.c | 44 +++++++++++++++++-
drivers/common/cnxk/roc_npc.h | 2 +
drivers/common/cnxk/roc_npc_priv.h | 11 +++++
.../common/cnxk/roc_platform_base_symbols.c | 1 +
drivers/net/cnxk/cnxk_eswitch.c | 2 +-
drivers/net/cnxk/cnxk_ethdev.c | 7 ++-
drivers/net/cnxk/cnxk_ethdev_devargs.c | 29 +++++++++++-
11 files changed, 163 insertions(+), 24 deletions(-)
diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst
index b5bd50ceea..239ebcd05c 100644
--- a/doc/guides/nics/cnxk.rst
+++ b/doc/guides/nics/cnxk.rst
@@ -183,8 +183,8 @@ Runtime Config Options
With the above configuration, higig2 will be enabled on that port and the
traffic on this port should be higig2 traffic only. Supported switch header
- types are "chlen24b", "chlen90b", "dsa", "exdsa", "higig2", "vlan_exdsa" and
- "pre_l2".
+ types are "chlen24b", "chlen90b", "dsa", "exdsa", "higig2", "vlan_exdsa",
+ "pre_l2" and "skip_size".
- ``Flow pre_l2 info`` (default ``0x0/0x0/0x0``)
@@ -212,6 +212,21 @@ Runtime Config Options
is 0 (i.e., left shift) then the shift count will be 1, that is, (8 - n),
where n is the absolute position of leftmost set bit.
+- ``Skip size info`` (default ``0x0``)
+
+ When the switch header type is set to "skip_size", the number of bytes to
+ skip before the Ethernet header can be configured using ``skip_size_info``
+ ``devargs`` parameter. The value is in hexadecimal format and the valid
+ range is 0x0 to 0xff. This configures the PKIND so that the NPC parser
+ skips the specified number of bytes.
+
+ For example::
+
+ -a 0002:02:00.0,switch_header="skip_size",skip_size_info=0x2
+
+ With the above configuration, 2 bytes will be skipped before the Ethernet
+ header when parsing the incoming packets.
+
- ``RSS tag as XOR`` (default ``0``)
The HW gives two options to configure the RSS adder i.e
diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index e31abf2234..1158ff50a7 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -462,8 +462,11 @@ struct ready_msg_rsp {
};
enum npc_pkind_type {
+ NPC_RX_SKIP_SIZE_PKIND = 46ULL,
+ NPC_RX_CPT_SKIP_SIZE_PKIND = 50ULL,
+ NPC_RX_CPT_HDR_PTP_PKIND = 54ULL,
NPC_RX_CUSTOM_PRE_L2_PKIND = 55ULL,
- NPC_RX_VLAN_EXDSA_PKIND = 56ULL,
+ NPC_RX_VLAN_EXDSA_PKIND,
NPC_RX_CHLEN24B_PKIND,
NPC_RX_CPT_HDR_PKIND,
NPC_RX_CHLEN90B_PKIND,
@@ -474,6 +477,8 @@ enum npc_pkind_type {
NPC_TX_DEF_PKIND,
};
+#define NPC_SKIP_SIZE_PKIND_MAX 4
+
/* Struct to set pkind */
struct npc_set_pkind {
struct mbox_msghdr hdr;
@@ -484,6 +489,7 @@ struct npc_set_pkind {
#define ROC_PRIV_FLAGS_EXDSA BIT_ULL(4)
#define ROC_PRIV_FLAGS_VLAN_EXDSA BIT_ULL(5)
#define ROC_PRIV_FLAGS_PRE_L2 BIT_ULL(6)
+#define ROC_PRIV_FLAGS_SKIP_SIZE BIT_ULL(7)
#define ROC_PRIV_FLAGS_CUSTOM BIT_ULL(63)
uint64_t __io mode;
#define PKIND_TX BIT_ULL(0)
@@ -499,6 +505,10 @@ struct npc_set_pkind {
/* Shift direction to get length of the
* header at var_len_off
*/
+ uint8_t __io skip_size;
+ /* Number of bytes to skip before the Ethernet header.
+ * Valid only in case custom flag.
+ */
};
/* Structure for requesting resource provisioning.
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index 8ba8b3e0b6..49ede85f9a 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -990,18 +990,14 @@ int __roc_api roc_nix_mac_stats_reset(struct roc_nix *roc_nix);
int __roc_api roc_nix_mac_fwdata_get(struct roc_nix *roc_nix, struct roc_nix_mac_fwdata *fwdata);
/* Ops */
-int __roc_api roc_nix_switch_hdr_set(struct roc_nix *roc_nix,
- uint64_t switch_header_type,
- uint8_t pre_l2_size_offset,
- uint8_t pre_l2_size_offset_mask,
- uint8_t pre_l2_size_shift_dir);
+int __roc_api roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
+ uint8_t pre_l2_size_offset, uint8_t pre_l2_size_offset_mask,
+ uint8_t pre_l2_size_shift_dir, uint8_t skip_size);
int __roc_api roc_nix_lso_fmt_setup(struct roc_nix *roc_nix);
-int __roc_api roc_nix_lso_fmt_get(struct roc_nix *roc_nix,
- uint8_t udp_tun[ROC_NIX_LSO_TUN_MAX],
+int __roc_api roc_nix_lso_fmt_get(struct roc_nix *roc_nix, uint8_t udp_tun[ROC_NIX_LSO_TUN_MAX],
uint8_t tun[ROC_NIX_LSO_TUN_MAX]);
int __roc_api roc_nix_lso_fmt_ipv4_frag_get(struct roc_nix *roc_nix);
-int __roc_api roc_nix_lso_custom_fmt_setup(struct roc_nix *roc_nix,
- struct nix_lso_format *fields,
+int __roc_api roc_nix_lso_custom_fmt_setup(struct roc_nix *roc_nix, struct nix_lso_format *fields,
uint16_t nb_fields);
int __roc_api roc_nix_lso_alt_flags_profile_setup(struct roc_nix *roc_nix,
nix_lso_alt_flg_format_t *fmt);
diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c
index 4653bb2049..13a548216b 100644
--- a/drivers/common/cnxk/roc_nix_ops.c
+++ b/drivers/common/cnxk/roc_nix_ops.c
@@ -501,17 +501,49 @@ roc_nix_lso_fmt_get(struct roc_nix *roc_nix,
return 0;
}
+static int
+skip_size_pkind_get(uint8_t skip_size, uint8_t *pkind)
+{
+ struct skip_size_pkind_cfg *cfg;
+ const struct plt_memzone *mz;
+ int i;
+
+ mz = plt_memzone_lookup(SKIP_SIZE_PKIND_MEMZONE);
+ if (!mz)
+ return -ENOMEM;
+ cfg = mz->addr;
+
+ for (i = 0; i < cfg->count; i++) {
+ if (cfg->entries[i].skip_size == skip_size) {
+ *pkind = cfg->entries[i].pkind;
+ return 0;
+ }
+ }
+
+ if (cfg->count >= NPC_SKIP_SIZE_PKIND_MAX) {
+ plt_err("skip_size PKIND limit (%d) reached", NPC_SKIP_SIZE_PKIND_MAX);
+ return -ENOSPC;
+ }
+
+ i = cfg->count;
+ cfg->entries[i].skip_size = skip_size;
+ cfg->entries[i].pkind = NPC_RX_SKIP_SIZE_PKIND + i;
+ *pkind = cfg->entries[i].pkind;
+ cfg->count++;
+ return 0;
+}
+
int
roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
- uint8_t pre_l2_size_offset,
- uint8_t pre_l2_size_offset_mask,
- uint8_t pre_l2_size_shift_dir)
+ uint8_t pre_l2_size_offset, uint8_t pre_l2_size_offset_mask,
+ uint8_t pre_l2_size_shift_dir, uint8_t skip_size)
{
struct nix *nix = roc_nix_to_nix_priv(roc_nix);
struct dev *dev = &nix->dev;
struct mbox *mbox = mbox_get(dev->mbox);
struct npc_set_pkind *req;
struct msg_resp *rsp;
+ uint8_t pkind = 0;
int rc = -ENOSPC;
if (switch_header_type == 0)
@@ -524,6 +556,7 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
switch_header_type != ROC_PRIV_FLAGS_EXDSA &&
switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA &&
switch_header_type != ROC_PRIV_FLAGS_PRE_L2 &&
+ switch_header_type != ROC_PRIV_FLAGS_SKIP_SIZE &&
switch_header_type != ROC_PRIV_FLAGS_CUSTOM) {
plt_err("switch header type is not supported");
rc = NIX_ERR_PARAM;
@@ -564,6 +597,13 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
req->var_len_off = pre_l2_size_offset;
req->var_len_off_mask = pre_l2_size_offset_mask;
req->shift_dir = pre_l2_size_shift_dir;
+ } else if (switch_header_type == ROC_PRIV_FLAGS_SKIP_SIZE) {
+ rc = skip_size_pkind_get(skip_size, &pkind);
+ if (rc)
+ goto exit;
+ req->mode = ROC_PRIV_FLAGS_CUSTOM;
+ req->pkind = pkind;
+ req->skip_size = skip_size;
}
req->dir = PKIND_RX;
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index a906fe0413..111ad0e8bb 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -420,6 +420,16 @@ roc_npc_init(struct roc_npc *roc_npc)
roc_npc->flow_age.age_flow_refcnt = 0;
+ /* Create skip-size PKIND memzone if it doesn't exist */
+ if (!plt_memzone_lookup(SKIP_SIZE_PKIND_MEMZONE)) {
+ const struct plt_memzone *mz;
+
+ mz = plt_memzone_reserve_cache_align(SKIP_SIZE_PKIND_MEMZONE,
+ sizeof(struct skip_size_pkind_cfg));
+ if (mz != NULL)
+ memset(mz->addr, 0, sizeof(struct skip_size_pkind_cfg));
+ }
+
return rc;
done:
@@ -457,12 +467,42 @@ roc_npc_fini(struct roc_npc *roc_npc)
npc->prio_flow_list = NULL;
}
+ {
+ const struct plt_memzone *mz;
+
+ mz = plt_memzone_lookup(SKIP_SIZE_PKIND_MEMZONE);
+ if (mz)
+ plt_memzone_free(mz);
+ }
+
return 0;
}
int
-roc_npc_validate_portid_action(struct roc_npc *roc_npc_src,
- struct roc_npc *roc_npc_dst)
+roc_npc_skip_size_pkind_get(struct roc_npc *roc_npc)
+{
+ struct skip_size_pkind_cfg *cfg;
+ const struct plt_memzone *mz;
+ int i;
+
+ if (roc_npc->switch_header_type != ROC_PRIV_FLAGS_SKIP_SIZE)
+ return -1;
+
+ mz = plt_memzone_lookup(SKIP_SIZE_PKIND_MEMZONE);
+ if (!mz)
+ return -1;
+ cfg = mz->addr;
+
+ for (i = 0; i < cfg->count; i++) {
+ if (cfg->entries[i].skip_size == roc_npc->skip_size)
+ return cfg->entries[i].pkind + NPC_SKIP_SIZE_PKIND_MAX;
+ }
+
+ return -1;
+}
+
+int
+roc_npc_validate_portid_action(struct roc_npc *roc_npc_src, struct roc_npc *roc_npc_dst)
{
struct roc_nix *roc_nix_src = roc_npc_src->roc_nix;
struct nix *nix_src = roc_nix_to_nix_priv(roc_nix_src);
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index 130990bda7..a7254f35ca 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -423,6 +423,7 @@ struct roc_npc {
*/
uint8_t pre_l2_size_shift_dir; /**< Shift direction to calculate size
*/
+ uint8_t skip_size; /**< Switch header skip size */
uint16_t flow_prealloc_size;
uint16_t flow_max_priority;
uint16_t channel;
@@ -506,4 +507,5 @@ void __roc_api roc_npc_sdp_channel_get(struct roc_npc *roc_npc, uint16_t *chan_b
uint16_t *chan_mask);
int __roc_api roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
uint64_t *count);
+int __roc_api roc_npc_skip_size_pkind_get(struct roc_npc *roc_npc);
#endif /* _ROC_NPC_H_ */
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index f8f4489f06..6a27f0e0fa 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -554,4 +554,15 @@ int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, const struct roc_npc_a
struct roc_npc_flow *flow);
void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc);
int npc_rss_free_grp_get(struct npc *npc, uint32_t *pos);
+
+#define SKIP_SIZE_PKIND_MEMZONE "roc_skip_size_pkind_cfg"
+
+struct skip_size_pkind_cfg {
+ uint8_t count;
+ struct {
+ uint8_t skip_size;
+ uint8_t pkind;
+ } entries[NPC_SKIP_SIZE_PKIND_MAX];
+};
+
#endif /* _ROC_NPC_PRIV_H_ */
diff --git a/drivers/common/cnxk/roc_platform_base_symbols.c b/drivers/common/cnxk/roc_platform_base_symbols.c
index ed34d4b05b..d1c9f2304d 100644
--- a/drivers/common/cnxk/roc_platform_base_symbols.c
+++ b/drivers/common/cnxk/roc_platform_base_symbols.c
@@ -492,6 +492,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_fini)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_validate_portid_action)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_flow_parse)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_sdp_channel_get)
+RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_skip_size_pkind_get)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_flow_create)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_flow_destroy)
RTE_EXPORT_INTERNAL_SYMBOL(roc_npc_flow_dump)
diff --git a/drivers/net/cnxk/cnxk_eswitch.c b/drivers/net/cnxk/cnxk_eswitch.c
index e45c7dfd07..7e717a2fbf 100644
--- a/drivers/net/cnxk/cnxk_eswitch.c
+++ b/drivers/net/cnxk/cnxk_eswitch.c
@@ -553,7 +553,7 @@ nix_lf_setup(struct cnxk_eswitch_dev *eswitch_dev)
goto free_cqs;
}
- rc = roc_nix_switch_hdr_set(nix, 0, 0, 0, 0);
+ rc = roc_nix_switch_hdr_set(nix, 0, 0, 0, 0, 0);
if (rc) {
plt_err("switch hdr set failed = %s(%d)", roc_error_msg_get(rc), rc);
goto free_cqs;
diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index c782dc51a8..a21e170229 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -1639,10 +1639,9 @@ cnxk_nix_configure(struct rte_eth_dev *eth_dev)
goto free_nix_lf;
}
- rc = roc_nix_switch_hdr_set(nix, dev->npc.switch_header_type,
- dev->npc.pre_l2_size_offset,
+ rc = roc_nix_switch_hdr_set(nix, dev->npc.switch_header_type, dev->npc.pre_l2_size_offset,
dev->npc.pre_l2_size_offset_mask,
- dev->npc.pre_l2_size_shift_dir);
+ dev->npc.pre_l2_size_shift_dir, dev->npc.skip_size);
if (rc) {
plt_err("Failed to enable switch type nix_lf rc=%d", rc);
goto free_nix_lf;
@@ -2364,7 +2363,7 @@ cnxk_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool reset)
return 0;
/* Disable switch hdr pkind */
- roc_nix_switch_hdr_set(&dev->nix, 0, 0, 0, 0);
+ roc_nix_switch_hdr_set(&dev->nix, 0, 0, 0, 0, 0);
/* Clear the flag since we are closing down */
dev->configured = 0;
diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c
index da8fc83f9d..ea18090919 100644
--- a/drivers/net/cnxk/cnxk_ethdev_devargs.c
+++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c
@@ -239,6 +239,25 @@ parse_switch_header_type(const char *key, const char *value, void *extra_args)
if (strcmp(value, "pre_l2") == 0)
*(uint16_t *)extra_args = ROC_PRIV_FLAGS_PRE_L2;
+ if (strcmp(value, "skip_size") == 0)
+ *(uint16_t *)extra_args = ROC_PRIV_FLAGS_SKIP_SIZE;
+
+ return 0;
+}
+
+static int
+parse_skip_size_info(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ errno = 0;
+ val = strtoul(value, NULL, 0);
+ if (errno || val > 255)
+ return -EINVAL;
+
+ *(uint16_t *)extra_args = val;
+
return 0;
}
@@ -303,6 +322,7 @@ parse_val_u16(const char *key, const char *value, void *extra_args)
#define CNXK_FORCE_TAIL_DROP "force_tail_drop"
#define CNXK_DIS_XQE_DROP "disable_xqe_drop"
#define CNXK_RXC_STEP "rxc_step"
+#define CNXK_SKIP_SIZE_INFO "skip_size_info"
int
cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
@@ -317,6 +337,7 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
uint16_t custom_meta_aura_dis = 0;
uint16_t flow_prealloc_size = 1;
uint16_t switch_header_type = 0;
+ uint16_t skip_size_info = 0;
uint16_t flow_max_priority = 3;
uint16_t outb_nb_crypto_qs = 1;
uint32_t ipsec_in_min_spi = 0;
@@ -392,6 +413,8 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
rte_kvargs_process(kvlist, CNXK_FORCE_TAIL_DROP, &parse_flag, &force_tail_drop);
rte_kvargs_process(kvlist, CNXK_DIS_XQE_DROP, &parse_flag, &dis_xqe_drop);
rte_kvargs_process(kvlist, CNXK_RXC_STEP, &parse_rxc_step, &rxc_step);
+ rte_kvargs_process(kvlist, CNXK_SKIP_SIZE_INFO, &parse_skip_size_info,
+ &skip_size_info);
rte_kvargs_free(kvlist);
null_devargs:
@@ -424,6 +447,7 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
dev->npc.flow_max_priority = flow_max_priority;
dev->npc.switch_header_type = switch_header_type;
+ dev->npc.skip_size = skip_size_info;
dev->npc.sdp_channel = sdp_chan.channel;
dev->npc.sdp_channel_mask = sdp_chan.mask;
dev->npc.is_sdp_mask_set = sdp_chan.is_sdp_mask_set;
@@ -448,7 +472,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_cnxk,
CNXK_MAX_SQB_COUNT "=<8-512>"
CNXK_FLOW_PREALLOC_SIZE "=<1-32>"
CNXK_FLOW_MAX_PRIORITY "=<1-32>"
- CNXK_SWITCH_HEADER_TYPE "=<higig2|dsa|chlen90b>"
+ CNXK_SWITCH_HEADER_TYPE "=<higig2|dsa|chlen90b|skip_size>"
CNXK_RSS_TAG_AS_XOR "=1"
CNXK_IPSEC_IN_MAX_SPI "=<1-65535>"
CNXK_OUTB_NB_DESC "=<1-65535>"
@@ -463,4 +487,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_cnxk,
CNXK_CUSTOM_META_AURA_DIS "=1"
CNXK_FORCE_TAIL_DROP "=1"
CNXK_DIS_XQE_DROP "=1"
- CNXK_RXC_STEP "=<0-1048575>");
+ CNXK_RXC_STEP "=<0-1048575>"
+ CNXK_SKIP_SIZE_INFO "=<0x0-0xff>");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 06/22] net/cnxk: reserve memory for lookup mem at probe
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
From: Nithin Dabilpuram <ndabilpuram@marvell.com>
Reserve memory for lookup mem at probe that is global for
all cnxk ethdev devices to avoid race at later stage.
Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
Changes in v2: No change.
drivers/net/cnxk/cnxk_ethdev.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 06d1c9b362..c782dc51a8 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -2220,6 +2220,12 @@ cnxk_eth_dev_init(struct rte_eth_dev *eth_dev)
/* Register callback for inline meta pool create 1:N pool:aura */
roc_nix_inl_custom_meta_pool_cb_register(cnxk_nix_inl_custom_meta_pool_cb);
+ /* Reserve memory for lookup_memory */
+ if (!cnxk_nix_fastpath_lookup_mem_get()) {
+ plt_err("Failed to reserve lookup memory rc=%d", rc);
+ goto dev_fini;
+ }
+
dev->eth_dev = eth_dev;
dev->configured = 0;
dev->ptype_disable = 0;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 05/22] common/cnxk: configure LSO mask for single segments
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj, Rahul Bhansali
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
Configures LSO flag mask for single packets.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2: No change.
drivers/common/cnxk/roc_nix_ops.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c
index 12a12c6e35..4653bb2049 100644
--- a/drivers/common/cnxk/roc_nix_ops.c
+++ b/drivers/common/cnxk/roc_nix_ops.c
@@ -239,6 +239,8 @@ nix_lso_ipv4(struct roc_nix *roc_nix)
/* First get flags profile to update v4 flags */
memset(&alt_flags, 0, sizeof(alt_flags));
+ alt_flags.s.alt_ssf_set = 0;
+ alt_flags.s.alt_ssf_mask = 0xFFFF;
alt_flags.s.alt_fsf_set = 0x2000;
alt_flags.s.alt_fsf_mask = 0x5FFF;
alt_flags.s.alt_msf_set = 0x2000;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 04/22] common/cnxk: update NIX irq handler
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj, Rahul Bhansali
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
Move queue context dump and register print before interrupt
clear in NIX irq handler.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2: No change.
drivers/common/cnxk/roc_nix_irq.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/common/cnxk/roc_nix_irq.c b/drivers/common/cnxk/roc_nix_irq.c
index 2b731302cd..6874435a4e 100644
--- a/drivers/common/cnxk/roc_nix_irq.c
+++ b/drivers/common/cnxk/roc_nix_irq.c
@@ -168,7 +168,7 @@ nix_lf_q_irq_get_and_clear(struct nix *nix, uint16_t q, uint32_t off,
reg = roc_atomic64_add_nosync(wdata, (int64_t *)(nix->base + off));
if (reg & BIT_ULL(42) /* OP_ERR */) {
- plt_err("Failed execute irq get off=0x%x", off);
+ plt_err("Failed execute irq get queue=%d off=0x%x", q, off);
return 0;
}
qint = reg & 0xff;
@@ -262,6 +262,10 @@ nix_lf_q_irq(void *param)
plt_err("Queue_intr=0x%" PRIx64 " qintx=%d pf=%d, vf=%d", intr, qintx,
dev->pf, dev->vf);
+ /* Dump registers to std out */
+ roc_nix_lf_reg_dump(nix_priv_to_roc_nix(nix), NULL);
+ roc_nix_queues_ctx_dump(nix_priv_to_roc_nix(nix), NULL);
+
/* Handle RQ interrupts */
for (q = 0; q < nix->nb_rx_queues; q++) {
rq = q % nix->qints;
@@ -323,10 +327,6 @@ nix_lf_q_irq(void *param)
/* Clear interrupt */
plt_write64(intr, nix->base + NIX_LF_QINTX_INT(qintx));
- /* Dump registers to std out */
- roc_nix_lf_reg_dump(nix_priv_to_roc_nix(nix), NULL);
- roc_nix_queues_ctx_dump(nix_priv_to_roc_nix(nix), NULL);
-
/* Call reset callback */
if (intr_cb && dev->ops->q_err_cb)
dev->ops->q_err_cb(nix_priv_to_roc_nix(nix), NULL);
--
2.34.1
^ permalink raw reply related
* [PATCH v2 03/22] common/cnxk: additional NIX SQ ctx fields prints
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj, Rahul Bhansali
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
Additional debug prints for CN20k NIX SQ ctx dump
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2: fix ubuntu clang stdatmoic compile failure.
drivers/common/cnxk/roc_nix_debug.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/common/cnxk/roc_nix_debug.c b/drivers/common/cnxk/roc_nix_debug.c
index 11994bf131..d4b2b86916 100644
--- a/drivers/common/cnxk/roc_nix_debug.c
+++ b/drivers/common/cnxk/roc_nix_debug.c
@@ -540,6 +540,8 @@ nix_cn10k_lf_sq_dump(__io struct nix_cn10k_sq_ctx_s *ctx, uint32_t *sqb_aura_p,
static inline void
nix_lf_sq_dump(__io struct nix_cn20k_sq_ctx_s *ctx, uint32_t *sqb_aura_p, FILE *file)
{
+ int64_t *sq_cnt_ptr = NULL;
+
nix_dump(file, "W0: sqe_way_mask \t\t%d\nW0: cq \t\t\t\t%d",
ctx->sqe_way_mask, ctx->cq);
nix_dump(file, "W0: sdp_mcast \t\t\t%d\nW0: substream \t\t\t0x%03x",
@@ -561,6 +563,7 @@ nix_lf_sq_dump(__io struct nix_cn20k_sq_ctx_s *ctx, uint32_t *sqb_aura_p, FILE *
nix_dump(file, "W2: smq_rr_count[ub:lb] \t\t%x:%x\n", ctx->smq_rr_count_ub,
ctx->smq_rr_count_lb);
+ nix_dump(file, "W3: update_sq_count\t\t%d\n", ctx->update_sq_count);
nix_dump(file, "W3: smq_next_sq_vld\t\t%d\nW3: smq_pend\t\t\t%d",
ctx->smq_next_sq_vld, ctx->smq_pend);
nix_dump(file, "W3: smenq_next_sqb_vld \t%d\nW3: head_offset\t\t\t%d",
@@ -588,6 +591,12 @@ nix_lf_sq_dump(__io struct nix_cn20k_sq_ctx_s *ctx, uint32_t *sqb_aura_p, FILE *
ctx->vfi_lso_sizem1);
nix_dump(file, "W9: vfi_lso_total\t\t%d", ctx->vfi_lso_total);
+ nix_dump(file, "W10: sq_count_iova \t\t0x%" PRIx64 "", (uint64_t)ctx->sq_count_iova);
+ sq_cnt_ptr = (int64_t *)(uintptr_t)(ctx->sq_count_iova << 3);
+ if (sq_cnt_ptr && ctx->update_sq_count)
+ nix_dump(file, "sq_count value \t\t0x%" PRIx64 "",
+ plt_atomic_load_explicit((uint64_t __plt_atomic *)sq_cnt_ptr,
+ plt_memory_order_relaxed));
nix_dump(file, "W10: scm_lso_rem \t\t0x%" PRIx64 "", (uint64_t)ctx->scm_lso_rem);
nix_dump(file, "W11: octs \t\t\t0x%" PRIx64 "", (uint64_t)ctx->octs);
nix_dump(file, "W12: pkts \t\t\t0x%" PRIx64 "", (uint64_t)ctx->pkts);
--
2.34.1
^ permalink raw reply related
* [PATCH v2 02/22] common/cnxk: add API of SA valid for cn20k platform
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj, Rahul Bhansali
In-Reply-To: <20260611142029.3351415-1-rbhansali@marvell.com>
Add API to get SA valid configuration for cn20k platform.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2: No change.
drivers/common/cnxk/cnxk_security.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/common/cnxk/cnxk_security.c b/drivers/common/cnxk/cnxk_security.c
index 6b51055100..6f46ad3276 100644
--- a/drivers/common/cnxk/cnxk_security.c
+++ b/drivers/common/cnxk/cnxk_security.c
@@ -606,6 +606,20 @@ cnxk_ot_ipsec_outb_sa_valid(struct roc_ot_ipsec_outb_sa *sa)
return !!sa->w2.s.valid;
}
+RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_inb_sa_valid)
+bool
+cnxk_ow_ipsec_inb_sa_valid(struct roc_ow_ipsec_inb_sa *sa)
+{
+ return !!sa->w2.s.valid;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_outb_sa_valid)
+bool
+cnxk_ow_ipsec_outb_sa_valid(struct roc_ow_ipsec_outb_sa *sa)
+{
+ return !!sa->w2.s.valid;
+}
+
RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_ivlen_get)
uint8_t
cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
--
2.34.1
^ permalink raw reply related
* [PATCH v2 01/22] net/cnxk: update mbuf next field for multi segment
From: Rahul Bhansali @ 2026-06-11 14:20 UTC (permalink / raw)
To: dev, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori,
Satha Rao, Harman Kalra
Cc: jerinj, Rahul Bhansali
In-Reply-To: <20260611073311.3129711-1-rbhansali@marvell.com>
As per the requirement of rte_mbuf_raw_reset_bulk(), the mbuf's
'next' and 'nb_segs' fields are required to be reset.
This reset these field for multi-segment mbufs on cn9k platform.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2: No change.
drivers/net/cnxk/cn9k_rx.h | 8 --------
drivers/net/cnxk/cn9k_tx.h | 42 ++++++++++++++++++--------------------
2 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/drivers/net/cnxk/cn9k_rx.h b/drivers/net/cnxk/cn9k_rx.h
index 79b56fe160..5ccdc5dee1 100644
--- a/drivers/net/cnxk/cn9k_rx.h
+++ b/drivers/net/cnxk/cn9k_rx.h
@@ -410,8 +410,6 @@ cn9k_nix_cqe_to_mbuf(const struct nix_cqe_hdr_s *cq, const uint32_t tag,
* Hence, flag argument is not required.
*/
nix_cqe_xtract_mseg(rx, mbuf, val, 0);
- else
- mbuf->next = NULL;
}
static inline uint16_t
@@ -826,12 +824,6 @@ cn9k_nix_recv_pkts_vector(void *rx_queue, struct rte_mbuf **rx_pkts,
nix_cqe_xtract_mseg((union nix_rx_parse_u *)
(cq0 + CQE_SZ(3) + 8), mbuf3,
mbuf_initializer, flags);
- } else {
- /* Update that no more segments */
- mbuf0->next = NULL;
- mbuf1->next = NULL;
- mbuf2->next = NULL;
- mbuf3->next = NULL;
}
/* Store the mbufs to rx_pkts */
diff --git a/drivers/net/cnxk/cn9k_tx.h b/drivers/net/cnxk/cn9k_tx.h
index 32665d2050..0ec448e36c 100644
--- a/drivers/net/cnxk/cn9k_tx.h
+++ b/drivers/net/cnxk/cn9k_tx.h
@@ -665,14 +665,14 @@ cn9k_nix_prepare_mseg(struct cn9k_eth_txq *txq, struct rte_mbuf *m, struct rte_m
#else
RTE_SET_USED(cookie);
#endif
-#ifdef RTE_ENABLE_ASSERT
- m->next = NULL;
- m->nb_segs = 1;
-#endif
- m = m_next;
- if (!m)
+ if (likely(!m_next))
goto done;
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F)) {
+ m->next = NULL;
+ m->nb_segs = 1;
+ }
+ m = m_next;
/* Fill mbuf segments */
do {
m_next = m->next;
@@ -704,12 +704,13 @@ cn9k_nix_prepare_mseg(struct cn9k_eth_txq *txq, struct rte_mbuf *m, struct rte_m
sg_u = sg->u;
slist++;
}
-#ifdef RTE_ENABLE_ASSERT
- m->next = NULL;
-#endif
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
+ m->next = NULL;
m = m_next;
} while (nb_segs);
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
+ rte_io_wmb();
done:
sg->u = sg_u;
sg->segs = i;
@@ -720,9 +721,6 @@ cn9k_nix_prepare_mseg(struct cn9k_eth_txq *txq, struct rte_mbuf *m, struct rte_m
segdw += (off >> 1) + 1 + !!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
send_hdr->w0.sizem1 = segdw - 1;
-#ifdef RTE_ENABLE_ASSERT
- rte_io_wmb();
-#endif
return segdw;
}
@@ -950,10 +948,10 @@ cn9k_nix_prepare_mseg_vec_list(struct cn9k_eth_txq *txq,
RTE_SET_USED(cookie);
#endif
-#ifdef RTE_ENABLE_ASSERT
- m->next = NULL;
- m->nb_segs = 1;
-#endif
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F)) {
+ m->next = NULL;
+ m->nb_segs = 1;
+ }
m = m_next;
/* Fill mbuf segments */
do {
@@ -984,9 +982,8 @@ cn9k_nix_prepare_mseg_vec_list(struct cn9k_eth_txq *txq,
sg_u = sg->u;
slist++;
}
-#ifdef RTE_ENABLE_ASSERT
- m->next = NULL;
-#endif
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
+ m->next = NULL;
m = m_next;
} while (nb_segs);
@@ -1002,9 +999,6 @@ cn9k_nix_prepare_mseg_vec_list(struct cn9k_eth_txq *txq,
!!(flags & NIX_TX_OFFLOAD_TSTAMP_F);
send_hdr->w0.sizem1 = segdw - 1;
-#ifdef RTE_ENABLE_ASSERT
- rte_io_wmb();
-#endif
return segdw;
}
@@ -1089,6 +1083,10 @@ cn9k_nix_xmit_pkts_mseg_vector(uint64x2_t *cmd0, uint64x2_t *cmd1,
}
}
+ /* Multi segment mbufs */
+ if (!(flags & NIX_TX_OFFLOAD_MBUF_NOFF_F))
+ rte_io_wmb();
+
for (j = 0; j < NIX_DESCS_PER_LOOP;) {
/* Fit consecutive packets in same LMTLINE. */
if ((segdw[j] + segdw[j + 1]) <= 8) {
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] bus/fslmc: fix shadowed variables in queue storage macros
From: David Marchand @ 2026-06-11 14:11 UTC (permalink / raw)
To: Weijun Pan, Hemant Agrawal, Sachin Saxena
Cc: Weijun Pan, dev, Jun Yang, stable, Thomas Monjalon,
Stephen Hemminger
In-Reply-To: <2S2V_VmSTBa7oGRJ0YAQqg@monjalon.net>
On Wed, 10 Jun 2026 at 16:16, Thomas Monjalon <thomas@monjalon.net> wrote:
>
> 07/04/2026 16:09, Stephen Hemminger:
> > Why are these not inline functions.
> > Macros with lower case names are likely place fore confusion like this?
>
> Hemant, Sachin, Weijun, please could you consider this comment?
Besides, I understand the intention behind bz 1744 is to re-enable Wshadow.
But after applying this fix, I still see many warnings after re-enabling:
$ git diff
diff --git a/drivers/bus/fslmc/meson.build b/drivers/bus/fslmc/meson.build
index ceae1c6c11..70098ad778 100644
--- a/drivers/bus/fslmc/meson.build
+++ b/drivers/bus/fslmc/meson.build
@@ -6,8 +6,6 @@ if not is_linux
reason = 'only supported on Linux'
endif
-cflags += no_shadow_cflag
-
deps += ['common_dpaax', 'eventdev', 'kvargs']
sources = files(
'fslmc_bus.c',
$ ./devtools/test-meson-builds.sh
...
../../../git/pub/dpdk.org/main/drivers/bus/fslmc/qbman/qbman_portal.c:
In function ‘qbman_swp_enqueue_multiple_cinh_read_direct’:
../../../git/pub/dpdk.org/main/drivers/bus/fslmc/qbman/qbman_portal.c:1092:47:
error: declaration of ‘d’ shadows a parameter [-Werror=shadow]
1092 | struct qbman_eq_desc *d = (struct
qbman_eq_desc *)p;
| ^
../../../git/pub/dpdk.org/main/drivers/bus/fslmc/qbman/qbman_portal.c:1047:45:
note: shadowed declaration is here
1047 | const struct qbman_eq_desc *d,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
../../../git/pub/dpdk.org/main/drivers/bus/fslmc/qbman/qbman_portal.c:
In function ‘qbman_swp_enqueue_multiple_cinh_direct’:
../../../git/pub/dpdk.org/main/drivers/bus/fslmc/qbman/qbman_portal.c:1161:47:
error: declaration of ‘d’ shadows a parameter [-Werror=shadow]
1161 | struct qbman_eq_desc *d = (struct
qbman_eq_desc *)p;
| ^
--
David Marchand
^ permalink raw reply related
* Re: [PATCH v2 0/2] dpaa2: fix error propagation in remove path
From: David Marchand @ 2026-06-11 13:52 UTC (permalink / raw)
To: Md Shofiqul Islam; +Cc: dev, hemant.agrawal, stable
In-Reply-To: <20260516110828.35701-1-shofiqtest@gmail.com>
On Sun, 17 May 2026 at 14:54, Md Shofiqul Islam <shofiqtest@gmail.com> wrote:
>
> This series fixes two bugs in the dpaa2/fslmc device removal path where
> error codes were silently discarded, making it impossible for callers to
> detect removal failures.
>
> Patch 1 fixes fslmc_bus_unplug() to capture and propagate the return
> value of drv->remove() instead of ignoring it.
>
> Patch 2 fixes dpaa2_qdma_remove() to return the actual error code from
> rte_dma_pmd_release() instead of unconditionally returning 0.
>
> v2:
> - bus/fslmc: use 'if (ret != 0)' style per DPDK coding standard
>
> Md Shofiqul Islam (2):
> bus/fslmc: fix ignored return value in fslmc_bus_unplug
> dma/dpaa2: fix dpaa2_qdma_remove always returning success
>
> drivers/bus/fslmc/fslmc_bus.c | 4 +++-
> drivers/dma/dpaa2/dpaa2_qdma.c | 2 +-
> 2 files changed, 4 insertions(+), 2 deletions(-)
Series applied, thanks.
--
David Marchand
^ permalink raw reply
* [PATCH 3/3] net/dpaa: remove ethdev pointer from bus device
From: David Marchand @ 2026-06-11 13:07 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, Sachin Saxena
In-Reply-To: <20260611130738.1720628-1-david.marchand@redhat.com>
Calling rte_eth_dev_allocated() is enough to retrieve the
ethdev device object.
This leaves no user of the ethdev field in the dpaa device object.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/dpaa/bus_dpaa_driver.h | 3 ---
drivers/net/dpaa/dpaa_ethdev.c | 3 +--
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/bus/dpaa/bus_dpaa_driver.h b/drivers/bus/dpaa/bus_dpaa_driver.h
index 0642aee14a..4aed83f84d 100644
--- a/drivers/bus/dpaa/bus_dpaa_driver.h
+++ b/drivers/bus/dpaa/bus_dpaa_driver.h
@@ -80,9 +80,6 @@ struct dpaa_device_id {
struct rte_dpaa_device {
struct rte_device device;
- union {
- struct rte_eth_dev *eth_dev;
- };
struct dpaa_device_id id;
struct rte_intr_handle *intr_handle;
enum rte_dpaa_type device_type; /**< Ethernet or crypto type device */
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 9f976d179b..967e814b5d 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2592,7 +2592,6 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv,
}
eth_dev->device = &dpaa_dev->device;
- dpaa_dev->eth_dev = eth_dev;
qman_ern_register_cb(dpaa_free_mbuf);
@@ -2678,7 +2677,7 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
PMD_INIT_FUNC_TRACE();
- eth_dev = dpaa_dev->eth_dev;
+ eth_dev = rte_eth_dev_allocated(dpaa_dev->device.name);
dpaa_eth_dev_close(eth_dev);
ret = rte_eth_dev_release_port(eth_dev);
dpaa_valid_dev--;
--
2.53.0
^ permalink raw reply related
* [PATCH 2/3] dma/dpaa: remove dmadev pointer from bus device
From: David Marchand @ 2026-06-11 13:07 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, Sachin Saxena, Gagandeep Singh
In-Reply-To: <20260611130738.1720628-1-david.marchand@redhat.com>
A driver .dev_close op is automatically called when releasing a dma
device.
Move device specific unitialisation in this driver .dev_close op.
This leaves no user of the dmadev field in the dpaa device object.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/dpaa/bus_dpaa_driver.h | 1 -
drivers/dma/dpaa/dpaa_qdma.c | 39 +++++++++++++++---------------
2 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/drivers/bus/dpaa/bus_dpaa_driver.h b/drivers/bus/dpaa/bus_dpaa_driver.h
index 6759792eea..0642aee14a 100644
--- a/drivers/bus/dpaa/bus_dpaa_driver.h
+++ b/drivers/bus/dpaa/bus_dpaa_driver.h
@@ -82,7 +82,6 @@ struct rte_dpaa_device {
struct rte_device device;
union {
struct rte_eth_dev *eth_dev;
- struct rte_dma_dev *dmadev;
};
struct dpaa_device_id id;
struct rte_intr_handle *intr_handle;
diff --git a/drivers/dma/dpaa/dpaa_qdma.c b/drivers/dma/dpaa/dpaa_qdma.c
index 74e23d2ee5..a695f58bc5 100644
--- a/drivers/dma/dpaa/dpaa_qdma.c
+++ b/drivers/dma/dpaa/dpaa_qdma.c
@@ -965,8 +965,24 @@ dpaa_qdma_start(__rte_unused struct rte_dma_dev *dev)
}
static int
-dpaa_qdma_close(__rte_unused struct rte_dma_dev *dev)
+dpaa_qdma_close(struct rte_dma_dev *dmadev)
{
+ struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
+ uint32_t i, j, regs_size;
+
+ regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
+ regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
+
+ for (i = 0; i < QDMA_BLOCKS; i++)
+ fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
+
+ for (i = 0; i < QDMA_BLOCKS; i++) {
+ for (j = 0; j < QDMA_QUEUES; j++)
+ fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
+ }
+
+ munmap(fsl_qdma->ctrl_base, regs_size);
+
return 0;
}
@@ -1420,7 +1436,6 @@ dpaa_qdma_probe(__rte_unused struct rte_dpaa_driver *dpaa_drv,
return -EINVAL;
}
- dpaa_dev->dmadev = dmadev;
dmadev->dev_ops = &dpaa_qdma_ops;
dmadev->device = &dpaa_dev->device;
dmadev->fp_obj->dev_private = dmadev->data->dev_private;
@@ -1445,24 +1460,8 @@ dpaa_qdma_probe(__rte_unused struct rte_dpaa_driver *dpaa_drv,
static int
dpaa_qdma_remove(struct rte_dpaa_device *dpaa_dev)
{
- struct rte_dma_dev *dmadev = dpaa_dev->dmadev;
- struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
- uint32_t i, j, regs_size;
-
- regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
- regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
-
- for (i = 0; i < QDMA_BLOCKS; i++)
- fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
-
- for (i = 0; i < QDMA_BLOCKS; i++) {
- for (j = 0; j < QDMA_QUEUES; j++)
- fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
- }
-
- munmap(fsl_qdma->ctrl_base, regs_size);
-
- (void)rte_dma_pmd_release(dpaa_dev->device.name);
+ if (rte_dma_pmd_release(dpaa_dev->device.name))
+ DPAA_QDMA_ERR("Device cleanup failed");
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 1/3] crypto/dpaa_sec: remove cryptodev pointer from bus device
From: David Marchand @ 2026-06-11 13:07 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal, Sachin Saxena, Gagandeep Singh
In-Reply-To: <20260611130738.1720628-1-david.marchand@redhat.com>
Calling rte_cryptodev_pmd_get_named_dev() is enough to retrieve the
crypto device object.
This leaves no user of the crypto_dev field in the dpaa device object.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/dpaa/bus_dpaa_driver.h | 1 -
drivers/crypto/dpaa_sec/dpaa_sec.c | 8 ++------
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/bus/dpaa/bus_dpaa_driver.h b/drivers/bus/dpaa/bus_dpaa_driver.h
index 5ddb52c419..6759792eea 100644
--- a/drivers/bus/dpaa/bus_dpaa_driver.h
+++ b/drivers/bus/dpaa/bus_dpaa_driver.h
@@ -82,7 +82,6 @@ struct rte_dpaa_device {
struct rte_device device;
union {
struct rte_eth_dev *eth_dev;
- struct rte_cryptodev *crypto_dev;
struct rte_dma_dev *dmadev;
};
struct dpaa_device_id id;
diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.c b/drivers/crypto/dpaa_sec/dpaa_sec.c
index 65bbd38b17..c53ee70853 100644
--- a/drivers/crypto/dpaa_sec/dpaa_sec.c
+++ b/drivers/crypto/dpaa_sec/dpaa_sec.c
@@ -3773,7 +3773,6 @@ cryptodev_dpaa_sec_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
struct rte_dpaa_device *dpaa_dev)
{
struct rte_cryptodev *cryptodev;
- char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
int retval;
struct rte_cryptodev_pmd_init_params init_params = {
.name = "",
@@ -3786,14 +3785,11 @@ cryptodev_dpaa_sec_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
- snprintf(cryptodev_name, sizeof(cryptodev_name), "%s", dpaa_dev->name);
-
- cryptodev = rte_cryptodev_pmd_create(cryptodev_name, &dpaa_dev->device, &init_params);
+ cryptodev = rte_cryptodev_pmd_create(dpaa_dev->name, &dpaa_dev->device, &init_params);
if (cryptodev == NULL) {
DPAA_SEC_ERR("failed to create cryptodev vdev");
return -ENOMEM;
}
- dpaa_dev->crypto_dev = cryptodev;
/* if sec device version is not configured */
if (!rta_get_sec_era()) {
@@ -3839,7 +3835,7 @@ cryptodev_dpaa_sec_remove(struct rte_dpaa_device *dpaa_dev)
struct rte_cryptodev *cryptodev;
int ret;
- cryptodev = dpaa_dev->crypto_dev;
+ cryptodev = rte_cryptodev_pmd_get_named_dev(dpaa_dev->name);
if (cryptodev == NULL)
return -ENODEV;
--
2.53.0
^ permalink raw reply related
* [PATCH 0/3] Cleanup rte_dpaa_device
From: David Marchand @ 2026-06-11 13:07 UTC (permalink / raw)
To: dev; +Cc: hemant.agrawal
Similar to the cleanup on the FSLMC bus, the DPAA bus device can
be cleaned.
The rte_dpaa_device object keeps track of a device class object
(cryptodev, dmadev, ethdev) which is a layer violation.
Make use of the device class respective infrastructure and remove those
back references.
Disclaimer: this series is untested as I don't have the hardware.
I only based those changes on look at the code and other drivers.
--
David Marchand
David Marchand (3):
crypto/dpaa_sec: remove cryptodev pointer from bus device
dma/dpaa: remove dmadev pointer from bus device
net/dpaa: remove ethdev pointer from bus device
drivers/bus/dpaa/bus_dpaa_driver.h | 5 ----
drivers/crypto/dpaa_sec/dpaa_sec.c | 8 ++----
drivers/dma/dpaa/dpaa_qdma.c | 39 +++++++++++++++---------------
drivers/net/dpaa/dpaa_ethdev.c | 3 +--
4 files changed, 22 insertions(+), 33 deletions(-)
--
2.53.0
^ permalink raw reply
* Re: [PATCH v3] net/iavf: fix to consolidate link change event handling
From: Bruce Richardson @ 2026-06-11 12:27 UTC (permalink / raw)
To: Loftus, Ciara
Cc: Mandal, Anurag, dev@dpdk.org, Medvedkin, Vladimir,
stable@dpdk.org
In-Reply-To: <DS4PPF6915D992B77353318BC850C46DA5C8E1B2@DS4PPF6915D992B.namprd11.prod.outlook.com>
On Thu, Jun 11, 2026 at 12:59:55PM +0100, Loftus, Ciara wrote:
> > Subject: Re: [PATCH v3] net/iavf: fix to consolidate link change event handling
> >
> > On Wed, Jun 10, 2026 at 03:34:27PM +0100, Loftus, Ciara wrote:
> > > > Subject: [PATCH v3] net/iavf: fix to consolidate link change event handling
> > > >
> > > > Handled link-change events through a common static function that
> > > > reads the correct advanced & legacy link fields properly and
> > > > updates no-poll/watchdog/LSC state consistently.
> > > >
> > > > Fixes: 5e03e316c753 ("net/iavf: handle virtchnl event message without
> > > > interrupt")
> > > > Fixes: 48de41ca11f0 ("net/avf: enable link status update")
> > > > Cc: stable@dpdk.org
> > > >
> > > > Signed-off-by: Anurag Mandal <anurag.mandal@intel.com>
> > >
> > > Thanks Anurag.
> > >
> > > Acked-by: Ciara Loftus <ciara.loftus@intel.com>
> > >
> > Just to confirm something here: does this change fix an actual underlying
> > issue, or is it just a code cleanup? If the latter we probably don't want
> > to backport it, but if it is a bug-fix, I'd like to include some details in
> > the commit log of what the observed issue was.
>
> Hi Bruce, I believe there 2 underlying issues being fixed here:
>
> 1. Ensuring LSC event is sent to the application AFTER configuring
> watchdog/no_poll state.
> 2. Ensuring watchdog is re-armed on LSC event, if a reset is detected.
> (Before it was only re-armed if link was down).
>
> The comment in the new function iavf_handle_link_change_event explains
> the reasoning. Perhaps an update to the commit message could be pulled
> from there.
>
> Thanks,
> Ciara
>
Patch applied to next-net-intel with title reworded and some additional
text on the commit log. Anurag and Ciara, please review the applied commit
log to check it is ok with you.
/Bruce
^ permalink raw reply
* RE: [PATCH v3] net/iavf: fix to consolidate link change event handling
From: Loftus, Ciara @ 2026-06-11 11:59 UTC (permalink / raw)
To: Richardson, Bruce
Cc: Mandal, Anurag, dev@dpdk.org, Medvedkin, Vladimir,
stable@dpdk.org
In-Reply-To: <aiqI5XxPOvu1m0Bj@bricha3-mobl1.ger.corp.intel.com>
> Subject: Re: [PATCH v3] net/iavf: fix to consolidate link change event handling
>
> On Wed, Jun 10, 2026 at 03:34:27PM +0100, Loftus, Ciara wrote:
> > > Subject: [PATCH v3] net/iavf: fix to consolidate link change event handling
> > >
> > > Handled link-change events through a common static function that
> > > reads the correct advanced & legacy link fields properly and
> > > updates no-poll/watchdog/LSC state consistently.
> > >
> > > Fixes: 5e03e316c753 ("net/iavf: handle virtchnl event message without
> > > interrupt")
> > > Fixes: 48de41ca11f0 ("net/avf: enable link status update")
> > > Cc: stable@dpdk.org
> > >
> > > Signed-off-by: Anurag Mandal <anurag.mandal@intel.com>
> >
> > Thanks Anurag.
> >
> > Acked-by: Ciara Loftus <ciara.loftus@intel.com>
> >
> Just to confirm something here: does this change fix an actual underlying
> issue, or is it just a code cleanup? If the latter we probably don't want
> to backport it, but if it is a bug-fix, I'd like to include some details in
> the commit log of what the observed issue was.
Hi Bruce, I believe there 2 underlying issues being fixed here:
1. Ensuring LSC event is sent to the application AFTER configuring
watchdog/no_poll state.
2. Ensuring watchdog is re-armed on LSC event, if a reset is detected.
(Before it was only re-armed if link was down).
The comment in the new function iavf_handle_link_change_event explains
the reasoning. Perhaps an update to the commit message could be pulled
from there.
Thanks,
Ciara
>
> Thanks,
> /Bruce
^ permalink raw reply
* Re: [PATCH v6] net/iavf: fix duplicate VF reset during PF reset recovery
From: Bruce Richardson @ 2026-06-11 10:18 UTC (permalink / raw)
To: Loftus, Ciara
Cc: Mandal, Anurag, dev@dpdk.org, Medvedkin, Vladimir,
stable@dpdk.org
In-Reply-To: <IA4PR11MB92783284E084FA4FEE8422638E1B2@IA4PR11MB9278.namprd11.prod.outlook.com>
On Thu, Jun 11, 2026 at 09:52:39AM +0100, Loftus, Ciara wrote:
> > Subject: [PATCH v6] net/iavf: fix duplicate VF reset during PF reset recovery
> >
> > During PF initiated reset recovery, iavf_dev_close() sends an
> > extra 'VIRTCHNL_OP_RESET_VF' while recovery is already in progress.
> > That second reset can leave PF/VF virtchnl state inconsistent and
> > cause 'VIRTCHNL_OP_CONFIG_VSI_QUEUES' to fail with 'ERR_PARAM' after
> > ToR link flap/power-cycle, leaving the VF unable to recover.
> > This results in connection loss.
> >
> > This patch introduces a new flag 'pf_reset_in_progress', which
> > is set only when iavf_handle_hw_reset() is entered for a
> > PF-initiated reset (vf_initiated_reset is false), and
> > it is cleared on exit.
> > The aforesaid flag is used to prevent sending close-time VF
> > reset and related close-time virtchnl operation messages to the
> > AdminQ when PF triggered reset recovery is set.
> > This is done to avoid duplicate VF reset requests while preserving
> > normal behavior for application-driven close or VF-initiated reinit.
> >
> > Fixes: 675a104e2e94 ("net/iavf: fix abnormal disable HW interrupt")
> > Fixes: b34fe66ea893 ("net/iavf: delay VF reset command")
> > Fixes: 5e03e316c753 ("net/iavf: handle virtchnl event message without
> > interrupt")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Anurag Mandal <anurag.mandal@intel.com>
>
> Thanks Anurag.
>
> Acked-by: Ciara Loftus <ciara.loftus@intel.com>
>
Applied to dpdk-next-net-intel.
Thanks,
/Bruce
^ permalink raw reply
* Re: [PATCH] eal: fix core_index for non-EAL registered threads
From: David Marchand @ 2026-06-11 10:13 UTC (permalink / raw)
To: Maxime Peim; +Cc: dev
In-Reply-To: <CACyZvzgxXHmfeXtCwV37VR7moci6d1p_chy5XVuLYZ1LufsdwA@mail.gmail.com>
On Wed, 10 Jun 2026 at 15:46, Maxime Peim <maxime.peim@gmail.com> wrote:
>
> I am not sure it works either, if the lcore are manual set with a gap: `--lcores=0,7` (from `eal_parse_lcores`):
> - lcore 0 will get core_index = 0
> - lcore 7 will get core_index = 1
>
> When calling `rte_thread_register` we will hit lcore=1 as first not-assigned lcore and set core_index=1 as well.
Ah ah yes...
> It seems like a solution should be to have a bitmap of the currently used core_index stored in the global config.
Yes, it seems the right way to handle this.
We have a rte_bitmap API but it is probably simpler to go with a rte_bitset.
--
David Marchand
^ permalink raw reply
* Re: [PATCH 00/13] Bus cleanup infrastructure and fixes
From: David Marchand @ 2026-06-11 10:09 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, fengchengwen
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
On Thu, 11 Jun 2026 at 11:46, David Marchand <david.marchand@redhat.com> wrote:
>
> This is a followup of the previous bus refactoring.
> See https://inbox.dpdk.org/dev/CAJFAV8zvFpLwz8SY8DUUezyJyM43eRZ17Yj30ex808eHC4ZE=g@mail.gmail.com/.
>
> This series refactors the bus cleanup infrastructure to reduce code
> duplication and fix resource leaks in several bus drivers.
> It should address the leak Thomas pointed at.
>
> The first part of the series (patches 1-8) addresses several bugs and
> inconsistencies:
> - Documentation and log message inconsistencies from earlier bus
> refactoring
> - Device list management issues in dma/idxd and bus/vdev
> - Resource leaks in PCI and VMBUS bus cleanup (mappings and interrupts)
> - Simplified device freeing in NXP buses (DPAA and FSLMC)
> - Deferred interrupt allocation to probe time (NXP buses, VMBUS)
>
> The core infrastructure changes (patches 9-10) introduce the generic
> cleanup framework:
> - Refactors unplug operations to be the counterpart of probe_device
> - Implements rte_bus_generic_cleanup() to centralize cleanup logic
> - Adds .free_device operation to struct rte_bus
> - Adds compile-time verification that rte_device is at offset 0
>
> The final patches (11-13) convert remaining buses to use the generic
> cleanup helper:
> - DPAA bus: add unplug support
> - VMBUS bus: switch to embedded device name and add unplug support
>
> After this series, most buses use the generic cleanup helper, eliminating
> duplicated code and ensuring consistent cleanup behavior across the
> codebase.
The remaining bus that do not use the generic helper are:
- dma/idxd which has no unplug support,
- bus/cdx which has unplug support, but no cleanup (it should not be
that complex to achieve, but I did not try),
- bus/fslmc which has unplug support, but a strange cleanup that
does not do much except release some hw resources,
One important point is that the series in its current form induces a
change in behavior.
rte_dev_remove (iow unplugging a device) now leaves the dev object in
the bus list.
I chose this implementation as it makes the API more symmetric
(allocations in .scan are released in .cleanup, allocations in
.probe_device are released in .unplug_device).
I wonder if this would be problematic for the vdev bus in some usecase
where many ports are hotplugged then unplugged and never reused.
--
David Marchand
^ permalink raw reply
* Re: [PATCH v3] net/iavf: fix to consolidate link change event handling
From: Bruce Richardson @ 2026-06-11 10:07 UTC (permalink / raw)
To: Loftus, Ciara
Cc: Mandal, Anurag, dev@dpdk.org, Medvedkin, Vladimir,
stable@dpdk.org
In-Reply-To: <IA4PR11MB927893A5541358313C538CA28E1A2@IA4PR11MB9278.namprd11.prod.outlook.com>
On Wed, Jun 10, 2026 at 03:34:27PM +0100, Loftus, Ciara wrote:
> > Subject: [PATCH v3] net/iavf: fix to consolidate link change event handling
> >
> > Handled link-change events through a common static function that
> > reads the correct advanced & legacy link fields properly and
> > updates no-poll/watchdog/LSC state consistently.
> >
> > Fixes: 5e03e316c753 ("net/iavf: handle virtchnl event message without
> > interrupt")
> > Fixes: 48de41ca11f0 ("net/avf: enable link status update")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Anurag Mandal <anurag.mandal@intel.com>
>
> Thanks Anurag.
>
> Acked-by: Ciara Loftus <ciara.loftus@intel.com>
>
Just to confirm something here: does this change fix an actual underlying
issue, or is it just a code cleanup? If the latter we probably don't want
to backport it, but if it is a bug-fix, I'd like to include some details in
the commit log of what the observed issue was.
Thanks,
/Bruce
^ permalink raw reply
* [PATCH 13/13] bus/vmbus: support unplug
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, fengchengwen, Long Li, Wei Hu
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
Add .unplug callback to handle driver removal, device unmapping, and
interrupt cleanup. This enables use of the generic bus cleanup helper.
The cleanup function was already performing these operations, so it
seems safe to expose them through the unplug operation.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/rel_notes/release_26_07.rst | 4 +++
drivers/bus/vmbus/vmbus_common.c | 37 ++++++++++----------------
2 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 966f6501b4..38e4dd87b3 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -118,6 +118,10 @@ New Features
Implemented device unplug operation to allow runtime removal of DPAA devices.
+* **bus/vmbus: Added unplug operation support.**
+
+ Implemented device unplug operation to allow runtime removal of VMBUS devices.
+
* **Added selective Rx in ethdev API.**
Some parts of packets may be discarded in Rx
diff --git a/drivers/bus/vmbus/vmbus_common.c b/drivers/bus/vmbus/vmbus_common.c
index 4c4170a4b5..419eb9b895 100644
--- a/drivers/bus/vmbus/vmbus_common.c
+++ b/drivers/bus/vmbus/vmbus_common.c
@@ -146,34 +146,23 @@ rte_vmbus_probe(void)
}
static int
-rte_vmbus_cleanup(struct rte_bus *bus)
+vmbus_unplug_device(struct rte_device *rte_dev)
{
- struct rte_vmbus_device *dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(dev, bus) {
- const struct rte_vmbus_driver *drv;
- int ret;
-
- if (!rte_dev_is_probed(&dev->device))
- continue;
- drv = RTE_BUS_DRIVER(dev->device.driver, *drv);
- if (drv->remove == NULL)
- continue;
+ const struct rte_vmbus_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
+ struct rte_vmbus_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
+ int ret = 0;
+ if (drv->remove != NULL) {
ret = drv->remove(dev);
if (ret < 0)
- error = -1;
-
- rte_vmbus_unmap_device(dev);
- rte_intr_instance_free(dev->intr_handle);
-
- dev->device.driver = NULL;
- rte_bus_remove_device(bus, &dev->device);
- free(dev);
+ return ret;
}
- return error;
+ rte_vmbus_unmap_device(dev);
+ rte_intr_instance_free(dev->intr_handle);
+ dev->intr_handle = NULL;
+
+ return 0;
}
static int
@@ -224,10 +213,12 @@ rte_vmbus_unregister(struct rte_vmbus_driver *driver)
struct rte_bus rte_vmbus_bus = {
.scan = rte_vmbus_scan,
.probe = rte_bus_generic_probe,
- .cleanup = rte_vmbus_cleanup,
+ .free_device = free,
+ .cleanup = rte_bus_generic_cleanup,
.find_device = rte_bus_generic_find_device,
.match = vmbus_bus_match,
.probe_device = vmbus_probe_device,
+ .unplug_device = vmbus_unplug_device,
.parse = vmbus_parse,
.dev_compare = vmbus_dev_compare,
};
--
2.53.0
^ permalink raw reply related
* [PATCH 12/13] bus/vmbus: store name in bus specific device
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, fengchengwen, Long Li, Wei Hu
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
The device name is allocated with strdup() during scan and freed in
several places. However, when this bus cleanup is converted to use the
EAL generic helper, freeing the device object will require a custom
helper to also free the device name (and for this, a cast will be
needed).
Instead, add an embedded name array to rte_vmbus_device structure
(char name[RTE_DEV_NAME_MAX_LEN]) which is sufficient for all VMBUS
device names (UUID format: 36 characters, or shorter legacy format).
This simplifies the device freeing to a simple free() call.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/vmbus/bus_vmbus_driver.h | 1 +
drivers/bus/vmbus/linux/vmbus_bus.c | 10 +++-------
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/bus/vmbus/bus_vmbus_driver.h b/drivers/bus/vmbus/bus_vmbus_driver.h
index 888d856141..706ff1fcf5 100644
--- a/drivers/bus/vmbus/bus_vmbus_driver.h
+++ b/drivers/bus/vmbus/bus_vmbus_driver.h
@@ -38,6 +38,7 @@ enum hv_uio_map {
*/
struct rte_vmbus_device {
struct rte_device device; /**< Inherit core device */
+ char name[RTE_DEV_NAME_MAX_LEN]; /**< VMBUS device name */
rte_uuid_t device_id; /**< VMBUS device id */
rte_uuid_t class_id; /**< VMBUS device type */
uint32_t relid; /**< id for primary */
diff --git a/drivers/bus/vmbus/linux/vmbus_bus.c b/drivers/bus/vmbus/linux/vmbus_bus.c
index 77d904ad6d..779ea50b92 100644
--- a/drivers/bus/vmbus/linux/vmbus_bus.c
+++ b/drivers/bus/vmbus/linux/vmbus_bus.c
@@ -280,15 +280,14 @@ vmbus_scan_one(const char *name)
char filename[PATH_MAX];
char dirname[PATH_MAX];
unsigned long tmp;
- char *dev_name;
dev = calloc(1, sizeof(*dev));
if (dev == NULL)
return -1;
- dev->device.name = dev_name = strdup(name);
- if (!dev->device.name)
+ if (rte_strscpy(dev->name, name, sizeof(dev->name)) < 0)
goto error;
+ dev->device.name = dev->name;
/* sysfs base directory
* /sys/bus/vmbus/devices/7a08391f-f5a0-4ac0-9802-d13fd964f8df
@@ -305,7 +304,6 @@ vmbus_scan_one(const char *name)
/* skip non-network devices */
if (rte_uuid_compare(dev->class_id, vmbus_nic_uuid) != 0) {
- free(dev_name);
free(dev);
return 0;
}
@@ -330,7 +328,7 @@ vmbus_scan_one(const char *name)
dev->monitor_id = UINT8_MAX;
}
- dev->device.devargs = rte_bus_find_devargs(&rte_vmbus_bus, dev_name);
+ dev->device.devargs = rte_bus_find_devargs(&rte_vmbus_bus, dev->name);
dev->device.numa_node = SOCKET_ID_ANY;
if (vmbus_use_numa(dev)) {
@@ -360,7 +358,6 @@ vmbus_scan_one(const char *name)
} else { /* already registered */
VMBUS_LOG(NOTICE,
"%s already registered", name);
- free(dev_name);
free(dev);
}
return 0;
@@ -371,7 +368,6 @@ vmbus_scan_one(const char *name)
error:
VMBUS_LOG(DEBUG, "failed");
- free(dev_name);
free(dev);
return -1;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 11/13] bus/dpaa: support unplug
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev
Cc: thomas, stephen, bruce.richardson, fengchengwen, Hemant Agrawal,
Sachin Saxena
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
Add .unplug callback to handle driver removal and interrupt cleanup.
This enables use of the generic bus cleanup helper while preserving
bus-specific cleanup (portal finish, global init reset).
The cleanup function was already performing these operations, so it
seems safe to expose them through the unplug operation.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/rel_notes/release_26_07.rst | 4 +++
drivers/bus/dpaa/dpaa_bus.c | 48 +++++++++++++++-----------
2 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 5d7aa8d1bf..966f6501b4 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -114,6 +114,10 @@ New Features
Added no-IOMMU mode for devices without or not enabling IOMMU/SVA.
+* **bus/dpaa: Added unplug operation support.**
+
+ Implemented device unplug operation to allow runtime removal of DPAA devices.
+
* **Added selective Rx in ethdev API.**
Some parts of packets may be discarded in Rx
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 69f071d007..6d4bec3751 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -785,34 +785,38 @@ dpaa_bus_probe_device(struct rte_driver *drv, struct rte_device *dev)
}
static int
-dpaa_bus_cleanup(struct rte_bus *bus)
+dpaa_bus_unplug_device(struct rte_device *rte_dev)
{
- struct rte_dpaa_device *dev;
+ const struct rte_dpaa_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
+ struct rte_dpaa_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
+ int ret = 0;
- BUS_INIT_FUNC_TRACE();
- RTE_BUS_FOREACH_DEV(dev, bus) {
- const struct rte_dpaa_driver *drv;
- int ret = 0;
-
- if (!rte_dev_is_probed(&dev->device))
- continue;
- drv = RTE_BUS_DRIVER(dev->device.driver, *drv);
- if (drv->remove == NULL)
- continue;
+ if (drv->remove != NULL) {
ret = drv->remove(dev);
- if (ret < 0) {
- rte_errno = errno;
- return -1;
- }
- rte_intr_instance_free(dev->intr_handle);
- dev->intr_handle = NULL;
- dev->device.driver = NULL;
+ if (ret < 0)
+ return ret;
}
+
+ rte_intr_instance_free(dev->intr_handle);
+ dev->intr_handle = NULL;
+
+ return 0;
+}
+
+static int
+dpaa_bus_cleanup(struct rte_bus *bus)
+{
+ int ret;
+
+ BUS_INIT_FUNC_TRACE();
+
+ ret = rte_bus_generic_cleanup(bus);
+
dpaa_portal_finish((void *)DPAA_PER_LCORE_PORTAL);
dpaa_bus_global_init = 0;
DPAA_BUS_DEBUG("Bus cleanup done");
- return 0;
+ return ret;
}
/* Adding destructor for double check in case non-gracefully
@@ -838,14 +842,16 @@ RTE_FINI_PRIO(dpaa_cleanup, 102)
static struct rte_bus rte_dpaa_bus = {
.scan = rte_dpaa_bus_scan,
.probe = rte_bus_generic_probe,
+ .free_device = free,
+ .cleanup = dpaa_bus_cleanup,
.parse = rte_dpaa_bus_parse,
.dev_compare = dpaa_bus_dev_compare,
.find_device = rte_bus_generic_find_device,
.get_iommu_class = rte_dpaa_get_iommu_class,
.match = dpaa_bus_match,
.probe_device = dpaa_bus_probe_device,
+ .unplug_device = dpaa_bus_unplug_device,
.dev_iterate = rte_bus_generic_dev_iterate,
- .cleanup = dpaa_bus_cleanup,
};
static struct rte_dpaa_bus_private dpaa_bus = {
--
2.53.0
^ permalink raw reply related
* [PATCH 10/13] bus: implement cleanup in EAL
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev
Cc: thomas, stephen, bruce.richardson, fengchengwen, Parav Pandit,
Xueming Li, Nipun Gupta, Nikhil Agarwal, Hemant Agrawal,
Sachin Saxena, Rosen Xu, Chenbo Xia, Tomasz Duszynski, Long Li,
Wei Hu, Kevin Laatz
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
Introduce a generic cleanup helper rte_bus_generic_cleanup() that
eliminates code duplication across bus cleanup implementations:
unplug probed devices, remove devargs, remove from bus list,
and free device structures.
Add .free_device operation to struct rte_bus to allow buses to specify
how to free their device structures.
Add compile-time check in RTE_REGISTER_BUS macro to verify rte_device
is at offset 0.
Update all buses for the new .cleanup and RTE_REGISTER_BUS prototypes.
Convert to rte_bus_generic_cleanup() the buses that have both a .cleanup
and .unplug: this requires implementing .free_device for them.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/auxiliary/auxiliary_common.c | 30 ++-----------------
drivers/bus/cdx/cdx.c | 2 +-
drivers/bus/dpaa/dpaa_bus.c | 6 ++--
drivers/bus/fslmc/fslmc_bus.c | 4 +--
drivers/bus/ifpga/ifpga_bus.c | 34 ++-------------------
drivers/bus/pci/pci_common.c | 30 ++++---------------
drivers/bus/platform/platform.c | 22 ++------------
drivers/bus/uacce/uacce.c | 30 ++-----------------
drivers/bus/vdev/vdev.c | 22 ++++----------
drivers/bus/vmbus/vmbus_common.c | 8 ++---
drivers/dma/idxd/idxd_bus.c | 2 +-
lib/eal/common/eal_common_bus.c | 33 +++++++++++++++++++-
lib/eal/include/bus_driver.h | 38 ++++++++++++++++++++++--
13 files changed, 102 insertions(+), 159 deletions(-)
diff --git a/drivers/bus/auxiliary/auxiliary_common.c b/drivers/bus/auxiliary/auxiliary_common.c
index 10f466e57a..6a1fc14d59 100644
--- a/drivers/bus/auxiliary/auxiliary_common.c
+++ b/drivers/bus/auxiliary/auxiliary_common.c
@@ -179,31 +179,6 @@ rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
rte_bus_remove_driver(&auxiliary_bus, &driver->driver);
}
-static int
-auxiliary_cleanup(void)
-{
- struct rte_auxiliary_device *dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(dev, &auxiliary_bus) {
- int ret;
-
- if (rte_dev_is_probed(&dev->device)) {
- ret = auxiliary_unplug_device(&dev->device);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
- }
- }
-
- rte_devargs_remove(dev->device.devargs);
- rte_bus_remove_device(&auxiliary_bus, &dev->device);
- free(dev);
- }
-
- return error;
-}
-
static int
auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
{
@@ -247,7 +222,8 @@ auxiliary_get_iommu_class(void)
struct rte_bus auxiliary_bus = {
.scan = auxiliary_scan,
.probe = rte_bus_generic_probe,
- .cleanup = auxiliary_cleanup,
+ .free_device = free,
+ .cleanup = rte_bus_generic_cleanup,
.find_device = rte_bus_generic_find_device,
.match = auxiliary_bus_match,
.probe_device = auxiliary_probe_device,
@@ -259,5 +235,5 @@ struct rte_bus auxiliary_bus = {
.dev_iterate = rte_bus_generic_dev_iterate,
};
-RTE_REGISTER_BUS(auxiliary, auxiliary_bus);
+RTE_REGISTER_BUS(auxiliary, auxiliary_bus, struct rte_auxiliary_device);
RTE_LOG_REGISTER_DEFAULT(auxiliary_bus_logtype, NOTICE);
diff --git a/drivers/bus/cdx/cdx.c b/drivers/bus/cdx/cdx.c
index c0b46a41ad..d070e3b2a8 100644
--- a/drivers/bus/cdx/cdx.c
+++ b/drivers/bus/cdx/cdx.c
@@ -439,5 +439,5 @@ static struct rte_bus rte_cdx_bus = {
.dev_iterate = rte_bus_generic_dev_iterate,
};
-RTE_REGISTER_BUS(cdx, rte_cdx_bus);
+RTE_REGISTER_BUS(cdx, rte_cdx_bus, struct rte_cdx_device);
RTE_LOG_REGISTER_DEFAULT(cdx_logtype_bus, NOTICE);
diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 3915e0a8b7..69f071d007 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -785,12 +785,12 @@ dpaa_bus_probe_device(struct rte_driver *drv, struct rte_device *dev)
}
static int
-dpaa_bus_cleanup(void)
+dpaa_bus_cleanup(struct rte_bus *bus)
{
struct rte_dpaa_device *dev;
BUS_INIT_FUNC_TRACE();
- RTE_BUS_FOREACH_DEV(dev, &rte_dpaa_bus) {
+ RTE_BUS_FOREACH_DEV(dev, bus) {
const struct rte_dpaa_driver *drv;
int ret = 0;
@@ -853,5 +853,5 @@ static struct rte_dpaa_bus_private dpaa_bus = {
.device_count = 0,
};
-RTE_REGISTER_BUS(dpaa_bus, rte_dpaa_bus);
+RTE_REGISTER_BUS(dpaa_bus, rte_dpaa_bus, struct rte_dpaa_device);
RTE_LOG_REGISTER_DEFAULT(dpaa_logtype_bus, NOTICE);
diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c
index 15164796ec..17350d69b8 100644
--- a/drivers/bus/fslmc/fslmc_bus.c
+++ b/drivers/bus/fslmc/fslmc_bus.c
@@ -414,7 +414,7 @@ fslmc_bus_match(const struct rte_driver *drv, const struct rte_device *dev)
}
static int
-rte_fslmc_close(void)
+rte_fslmc_close(struct rte_bus *bus __rte_unused)
{
int ret = 0;
@@ -549,5 +549,5 @@ struct rte_bus rte_fslmc_bus = {
.dev_iterate = rte_bus_generic_dev_iterate,
};
-RTE_REGISTER_BUS(fslmc, rte_fslmc_bus);
+RTE_REGISTER_BUS(fslmc, rte_fslmc_bus, struct rte_dpaa2_device);
RTE_LOG_REGISTER_DEFAULT(dpaa2_logtype_bus, NOTICE);
diff --git a/drivers/bus/ifpga/ifpga_bus.c b/drivers/bus/ifpga/ifpga_bus.c
index 394b777916..e62cf371bd 100644
--- a/drivers/bus/ifpga/ifpga_bus.c
+++ b/drivers/bus/ifpga/ifpga_bus.c
@@ -295,35 +295,6 @@ ifpga_unplug_device(struct rte_device *dev)
return 0;
}
-/*
- * Cleanup the content of the Intel FPGA bus, and call the remove() function
- * for all registered devices.
- */
-static int
-ifpga_cleanup(void)
-{
- struct rte_afu_device *afu_dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(afu_dev, &rte_ifpga_bus) {
- int ret = 0;
-
- if (rte_dev_is_probed(&afu_dev->device)) {
- ret = ifpga_unplug_device(&afu_dev->device);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
- }
- }
-
- rte_devargs_remove(afu_dev->device.devargs);
- rte_bus_remove_device(&rte_ifpga_bus, &afu_dev->device);
- free(afu_dev);
- }
-
- return error;
-}
-
static int
ifpga_parse(const char *name, void *addr)
{
@@ -371,7 +342,8 @@ ifpga_parse(const char *name, void *addr)
static struct rte_bus rte_ifpga_bus = {
.scan = ifpga_scan,
.probe = rte_bus_generic_probe,
- .cleanup = ifpga_cleanup,
+ .free_device = free,
+ .cleanup = rte_bus_generic_cleanup,
.find_device = rte_bus_generic_find_device,
.match = ifpga_bus_match,
.probe_device = ifpga_probe_device,
@@ -379,7 +351,7 @@ static struct rte_bus rte_ifpga_bus = {
.parse = ifpga_parse,
};
-RTE_REGISTER_BUS(ifpga, rte_ifpga_bus);
+RTE_REGISTER_BUS(ifpga, rte_ifpga_bus, struct rte_afu_device);
RTE_INIT(ifpga_bus_init)
{
RTE_VERIFY(strcmp(rte_ifpga_bus.name, RTE_STR(IFPGA_BUS_NAME)) == 0);
diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c
index bf4822f7ec..dcc94b6bbd 100644
--- a/drivers/bus/pci/pci_common.c
+++ b/drivers/bus/pci/pci_common.c
@@ -317,29 +317,10 @@ pci_unplug_device(struct rte_device *rte_dev)
return 0;
}
-static int
-pci_cleanup(void)
+static void
+pci_free_device(void *dev)
{
- struct rte_pci_device *dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(dev, &rte_pci_bus) {
- int ret = 0;
-
- if (rte_dev_is_probed(&dev->device)) {
- ret = pci_unplug_device(&dev->device);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
- }
- }
-
- rte_devargs_remove(dev->device.devargs);
- rte_bus_remove_device(&rte_pci_bus, &dev->device);
- pci_free(RTE_PCI_DEVICE_INTERNAL(dev));
- }
-
- return error;
+ pci_free(RTE_PCI_DEVICE_INTERNAL(dev));
}
/* dump one device */
@@ -743,7 +724,8 @@ struct rte_bus rte_pci_bus = {
.allow_multi_probe = true,
.scan = rte_pci_scan,
.probe = rte_bus_generic_probe,
- .cleanup = pci_cleanup,
+ .free_device = pci_free_device,
+ .cleanup = rte_bus_generic_cleanup,
.find_device = rte_bus_generic_find_device,
.match = pci_bus_match,
.probe_device = pci_probe_device,
@@ -759,5 +741,5 @@ struct rte_bus rte_pci_bus = {
.sigbus_handler = pci_sigbus_handler,
};
-RTE_REGISTER_BUS(pci, rte_pci_bus);
+RTE_REGISTER_BUS(pci, rte_pci_bus, struct rte_pci_device);
RTE_LOG_REGISTER_DEFAULT(pci_bus_logtype, NOTICE);
diff --git a/drivers/bus/platform/platform.c b/drivers/bus/platform/platform.c
index 5b3c78a505..cb315144b8 100644
--- a/drivers/bus/platform/platform.c
+++ b/drivers/bus/platform/platform.c
@@ -491,26 +491,11 @@ platform_bus_get_iommu_class(void)
return RTE_IOVA_DC;
}
-static int
-platform_bus_cleanup(void)
-{
- struct rte_platform_device *pdev;
-
- RTE_BUS_FOREACH_DEV(pdev, &platform_bus) {
- if (rte_dev_is_probed(&pdev->device))
- platform_bus_unplug_device(&pdev->device);
-
- rte_devargs_remove(pdev->device.devargs);
- rte_bus_remove_device(&platform_bus, &pdev->device);
- free(pdev);
- }
-
- return 0;
-}
-
static struct rte_bus platform_bus = {
.scan = platform_bus_scan,
.probe = rte_bus_generic_probe,
+ .free_device = free,
+ .cleanup = rte_bus_generic_cleanup,
.find_device = rte_bus_generic_find_device,
.match = platform_bus_match,
.probe_device = platform_bus_probe_device,
@@ -520,8 +505,7 @@ static struct rte_bus platform_bus = {
.dma_unmap = platform_bus_dma_unmap,
.get_iommu_class = platform_bus_get_iommu_class,
.dev_iterate = rte_bus_generic_dev_iterate,
- .cleanup = platform_bus_cleanup,
};
-RTE_REGISTER_BUS(platform, platform_bus);
+RTE_REGISTER_BUS(platform, platform_bus, struct rte_platform_device);
RTE_LOG_REGISTER_DEFAULT(platform_bus_logtype, NOTICE);
diff --git a/drivers/bus/uacce/uacce.c b/drivers/bus/uacce/uacce.c
index bfe1f26557..e2763b26d5 100644
--- a/drivers/bus/uacce/uacce.c
+++ b/drivers/bus/uacce/uacce.c
@@ -402,31 +402,6 @@ uacce_unplug_device(struct rte_device *rte_dev)
return 0;
}
-static int
-uacce_cleanup(void)
-{
- struct rte_uacce_device *dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(dev, &uacce_bus) {
- int ret = 0;
-
- if (rte_dev_is_probed(&dev->device)) {
- ret = uacce_unplug_device(&dev->device);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
- }
- }
-
- rte_devargs_remove(dev->device.devargs);
- rte_bus_remove_device(&uacce_bus, &dev->device);
- free(dev);
- }
-
- return error;
-}
-
static int
uacce_parse(const char *name, void *addr)
{
@@ -551,7 +526,8 @@ rte_uacce_unregister(struct rte_uacce_driver *driver)
static struct rte_bus uacce_bus = {
.scan = uacce_scan,
.probe = rte_bus_generic_probe,
- .cleanup = uacce_cleanup,
+ .free_device = free,
+ .cleanup = rte_bus_generic_cleanup,
.match = uacce_bus_match,
.probe_device = uacce_probe_device,
.unplug_device = uacce_unplug_device,
@@ -560,5 +536,5 @@ static struct rte_bus uacce_bus = {
.dev_iterate = rte_bus_generic_dev_iterate,
};
-RTE_REGISTER_BUS(uacce, uacce_bus);
+RTE_REGISTER_BUS(uacce, uacce_bus, struct rte_uacce_device);
RTE_LOG_REGISTER_DEFAULT(uacce_bus_logtype, NOTICE);
diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
index c2cd642119..bb536803e4 100644
--- a/drivers/bus/vdev/vdev.c
+++ b/drivers/bus/vdev/vdev.c
@@ -548,25 +548,12 @@ vdev_scan(void)
}
static int
-vdev_cleanup(void)
+vdev_cleanup(struct rte_bus *bus)
{
- struct rte_vdev_device *dev;
- int error = 0;
+ int error;
rte_spinlock_recursive_lock(&vdev_device_list_lock);
- RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
- int ret;
-
- if (rte_dev_is_probed(&dev->device)) {
- ret = vdev_unplug_device(&dev->device);
- if (ret < 0)
- error = -1;
- }
-
- rte_devargs_remove(dev->device.devargs);
- rte_bus_remove_device(&rte_vdev_bus, &dev->device);
- free(dev);
- }
+ error = rte_bus_generic_cleanup(bus);
rte_spinlock_recursive_unlock(&vdev_device_list_lock);
return error;
@@ -607,6 +594,7 @@ vdev_get_iommu_class(void)
static struct rte_bus rte_vdev_bus = {
.scan = vdev_scan,
.probe = rte_bus_generic_probe,
+ .free_device = free,
.cleanup = vdev_cleanup,
.find_device = vdev_find_device,
.match = vdev_bus_match,
@@ -619,5 +607,5 @@ static struct rte_bus rte_vdev_bus = {
.dev_iterate = rte_bus_generic_dev_iterate,
};
-RTE_REGISTER_BUS(vdev, rte_vdev_bus);
+RTE_REGISTER_BUS(vdev, rte_vdev_bus, struct rte_vdev_device);
RTE_LOG_REGISTER_DEFAULT(vdev_logtype_bus, NOTICE);
diff --git a/drivers/bus/vmbus/vmbus_common.c b/drivers/bus/vmbus/vmbus_common.c
index b6ae82915f..4c4170a4b5 100644
--- a/drivers/bus/vmbus/vmbus_common.c
+++ b/drivers/bus/vmbus/vmbus_common.c
@@ -146,12 +146,12 @@ rte_vmbus_probe(void)
}
static int
-rte_vmbus_cleanup(void)
+rte_vmbus_cleanup(struct rte_bus *bus)
{
struct rte_vmbus_device *dev;
int error = 0;
- RTE_BUS_FOREACH_DEV(dev, &rte_vmbus_bus) {
+ RTE_BUS_FOREACH_DEV(dev, bus) {
const struct rte_vmbus_driver *drv;
int ret;
@@ -169,7 +169,7 @@ rte_vmbus_cleanup(void)
rte_intr_instance_free(dev->intr_handle);
dev->device.driver = NULL;
- rte_bus_remove_device(&rte_vmbus_bus, &dev->device);
+ rte_bus_remove_device(bus, &dev->device);
free(dev);
}
@@ -232,5 +232,5 @@ struct rte_bus rte_vmbus_bus = {
.dev_compare = vmbus_dev_compare,
};
-RTE_REGISTER_BUS(vmbus, rte_vmbus_bus);
+RTE_REGISTER_BUS(vmbus, rte_vmbus_bus, struct rte_vmbus_device);
RTE_LOG_REGISTER_DEFAULT(vmbus_logtype_bus, NOTICE);
diff --git a/drivers/dma/idxd/idxd_bus.c b/drivers/dma/idxd/idxd_bus.c
index 2ec526ec09..34fd9f90c9 100644
--- a/drivers/dma/idxd/idxd_bus.c
+++ b/drivers/dma/idxd/idxd_bus.c
@@ -346,7 +346,7 @@ dsa_addr_parse(const char *name, void *addr)
return 0;
}
-RTE_REGISTER_BUS(dsa, dsa_bus);
+RTE_REGISTER_BUS(dsa, dsa_bus, struct rte_dsa_device);
RTE_INIT(dsa_bus_init)
{
rte_bus_add_driver(&dsa_bus, &dsa_driver);
diff --git a/lib/eal/common/eal_common_bus.c b/lib/eal/common/eal_common_bus.c
index ca13ccce5b..9ba23516ee 100644
--- a/lib/eal/common/eal_common_bus.c
+++ b/lib/eal/common/eal_common_bus.c
@@ -124,6 +124,37 @@ rte_bus_generic_probe(struct rte_bus *bus)
return (probed && probed == failed) ? -1 : 0;
}
+/*
+ * Generic cleanup function for buses.
+ * Iterates through all devices on the bus, unplugs probed devices,
+ * removes devargs, removes devices from the bus list, and frees device structures.
+ */
+RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_generic_cleanup)
+int
+rte_bus_generic_cleanup(struct rte_bus *bus)
+{
+ struct rte_device *dev;
+ int error = 0;
+
+ RTE_VERIFY(bus->free_device);
+ RTE_VERIFY(bus->unplug_device);
+
+ while ((dev = TAILQ_FIRST(&bus->device_list)) != NULL) {
+ if (rte_dev_is_probed(dev)) {
+ if (bus->unplug_device && bus->unplug_device(dev) < 0) {
+ rte_errno = errno;
+ error = -1;
+ }
+ }
+
+ rte_devargs_remove(dev->devargs);
+ rte_bus_remove_device(bus, dev);
+ bus->free_device(dev);
+ }
+
+ return error;
+}
+
/* Probe all devices of all buses */
RTE_EXPORT_SYMBOL(rte_bus_probe)
int
@@ -164,7 +195,7 @@ eal_bus_cleanup(void)
TAILQ_FOREACH(bus, &rte_bus_list, next) {
if (bus->cleanup == NULL)
continue;
- if (bus->cleanup() != 0)
+ if (bus->cleanup(bus) != 0)
ret = -1;
}
diff --git a/lib/eal/include/bus_driver.h b/lib/eal/include/bus_driver.h
index 1baf024539..c7b956833c 100644
--- a/lib/eal/include/bus_driver.h
+++ b/lib/eal/include/bus_driver.h
@@ -6,6 +6,7 @@
#define BUS_DRIVER_H
#include <rte_bus.h>
+#include <rte_common.h>
#include <rte_compat.h>
#include <rte_dev.h>
#include <rte_eal.h>
@@ -239,17 +240,31 @@ typedef int (*rte_bus_hot_unplug_handler_t)(struct rte_device *dev);
*/
typedef int (*rte_bus_sigbus_handler_t)(const void *failure_addr);
+/**
+ * Free a bus-specific device structure.
+ *
+ * @param device
+ * Generic device pointer to free (will be cast to bus-specific type).
+ */
+typedef void (*rte_bus_free_device_t)(void *device);
+
/**
* Implementation specific cleanup function which is responsible for cleaning up
* devices on that bus with applicable drivers.
*
+ * The cleanup operation is the counterpart to scan, removing all devices added
+ * during scan.
+ *
* This is called while iterating over each registered bus.
*
+ * @param bus
+ * Pointer to the bus to cleanup.
+ *
* @return
* 0 for successful cleanup
* !0 for any error during cleanup
*/
-typedef int (*rte_bus_cleanup_t)(void);
+typedef int (*rte_bus_cleanup_t)(struct rte_bus *bus);
/**
* Check if a driver matches a device.
@@ -349,6 +364,7 @@ struct rte_bus {
/**< handle hot-unplug failure on the bus */
rte_bus_sigbus_handler_t sigbus_handler;
/**< handle sigbus error on the bus */
+ rte_bus_free_device_t free_device; /**< Free bus-specific device */
rte_bus_cleanup_t cleanup; /**< Cleanup devices on bus */
RTE_TAILQ_HEAD(, rte_device) device_list; /**< List of devices on the bus */
RTE_TAILQ_HEAD(, rte_driver) driver_list; /**< List of drivers on the bus */
@@ -414,9 +430,10 @@ void *rte_bus_generic_dev_iterate(const struct rte_bus *bus,
* Helper for Bus registration.
* The constructor has higher priority than PMD constructors.
*/
-#define RTE_REGISTER_BUS(nm, bus) \
+#define RTE_REGISTER_BUS(nm, bus, bus_dev_type) \
RTE_INIT_PRIO(businitfn_ ##nm, BUS) \
{\
+ RTE_BUILD_BUG_ON(offsetof(typeof(bus_dev_type), device) != 0); \
(bus).name = RTE_STR(nm);\
rte_bus_register(&bus); \
}
@@ -637,6 +654,23 @@ struct rte_driver *rte_bus_find_driver(const struct rte_bus *bus, const struct r
__rte_internal
int rte_bus_generic_probe(struct rte_bus *bus);
+/**
+ * Generic cleanup function for buses.
+ *
+ * Iterates through all devices on the bus, unplugs probed devices,
+ * removes devargs, removes devices from the bus list, and frees device structures.
+ *
+ * This function can be used by buses that don't require special cleanup
+ * logic and just need the standard device cleanup sequence.
+ *
+ * @param bus
+ * Pointer to the bus to cleanup.
+ * @return
+ * 0 on success, -1 if any errors occurred during cleanup.
+ */
+__rte_internal
+int rte_bus_generic_cleanup(struct rte_bus *bus);
+
#ifdef __cplusplus
}
#endif
--
2.53.0
^ permalink raw reply related
* [PATCH 09/13] bus: align unplug with device probe
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev
Cc: thomas, stephen, bruce.richardson, fengchengwen, Parav Pandit,
Xueming Li, Nipun Gupta, Nikhil Agarwal, Hemant Agrawal,
Sachin Saxena, Rosen Xu, Chenbo Xia, Tomasz Duszynski
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
Refactor bus unplug operations to be the counterpart of probe_device.
The (renamed) unplug operation now only handles:
- Driver removal (calling the driver's remove callback)
- Freeing probe-allocated resources (interrupts, mappings)
Device deletion (devargs removal, bus removal, freeing device
structure) is now handled only during bus cleanup, not in unplug.
Additionally, move driver pointer clearing from individual bus unplug
operations to EAL's local_dev_remove() where the unplug operation is
invoked. This centralizes driver lifecycle management and eliminates
code duplication across bus drivers.
For vdev, add a check in rte_vdev_uninit() since this public API can
be called on devices without a driver attached.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
doc/guides/prog_guide/device_hotplug.rst | 18 ++++---
drivers/bus/auxiliary/auxiliary_common.c | 46 ++++++----------
drivers/bus/cdx/cdx.c | 29 ++--------
drivers/bus/fslmc/fslmc_bus.c | 5 +-
drivers/bus/ifpga/ifpga_bus.c | 63 ++++++++++------------
drivers/bus/pci/pci_common.c | 57 ++++----------------
drivers/bus/platform/platform.c | 16 +++---
drivers/bus/uacce/uacce.c | 67 ++++++++----------------
drivers/bus/vdev/vdev.c | 53 ++++++++-----------
lib/eal/common/eal_common_dev.c | 8 +--
lib/eal/include/bus_driver.h | 4 +-
11 files changed, 127 insertions(+), 239 deletions(-)
diff --git a/doc/guides/prog_guide/device_hotplug.rst b/doc/guides/prog_guide/device_hotplug.rst
index 7eb7fbcc2b..d21ba0c244 100644
--- a/doc/guides/prog_guide/device_hotplug.rst
+++ b/doc/guides/prog_guide/device_hotplug.rst
@@ -165,7 +165,7 @@ using ``rte_dev_event_callback_register()`` function.
on the device in question.
When ``RTE_DEV_EVENT_REMOVE`` event is delivered,
it indicates that the kernel has removed the device;
- the application should call ``rte_dev_remove()`` to clean up EAL resources.
+ the application should call ``rte_dev_remove()`` to unplug the device driver.
Event Notification Usage
@@ -256,13 +256,17 @@ When ``rte_dev_remove()`` is called, the following sequence occurs:
See `Multi-process Synchronization`_ for details.
#. **Device Unplug**:
- The bus's ``unplug()`` method is called (``dev->bus->unplug()``),
- which triggers the driver's remove function.
- This typically stops device operations, releases device resources,
- unmaps memory regions, and unregisters from subsystems.
+ The bus's ``unplug_device()`` method is called (``dev->bus->unplug_device()``),
+ which triggers the driver's remove function
+ and releases resources allocated during probe
+ (such as interrupt handles and device memory mappings).
-#. **Devargs Cleanup**:
- The devargs associated with the device are removed from the global list.
+.. note::
+
+ The device structure, its devargs, and its entry in the bus device list
+ are NOT freed during ``rte_dev_remove()``.
+ They remain in memory until ``rte_eal_cleanup()`` is called,
+ at which point the bus's ``cleanup()`` method handles complete device deletion.
Multi-process Synchronization
diff --git a/drivers/bus/auxiliary/auxiliary_common.c b/drivers/bus/auxiliary/auxiliary_common.c
index 048aacf254..10f466e57a 100644
--- a/drivers/bus/auxiliary/auxiliary_common.c
+++ b/drivers/bus/auxiliary/auxiliary_common.c
@@ -122,13 +122,11 @@ auxiliary_probe_device(struct rte_driver *drv, struct rte_device *dev)
return ret;
}
-/*
- * Call the remove() function of the driver.
- */
static int
-rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device *dev)
+auxiliary_unplug_device(struct rte_device *rte_dev)
{
- const struct rte_auxiliary_driver *drv = RTE_BUS_DRIVER(dev->device.driver, *drv);
+ const struct rte_auxiliary_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
+ struct rte_auxiliary_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
int ret = 0;
AUXILIARY_LOG(DEBUG, "Driver %s remove auxiliary device %s on NUMA node %i",
@@ -140,8 +138,8 @@ rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device *dev)
return ret;
}
- /* clear driver structure */
- dev->device.driver = NULL;
+ rte_intr_instance_free(dev->intr_handle);
+ dev->intr_handle = NULL;
return 0;
}
@@ -181,22 +179,6 @@ rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
rte_bus_remove_driver(&auxiliary_bus, &driver->driver);
}
-static int
-auxiliary_unplug(struct rte_device *dev)
-{
- struct rte_auxiliary_device *adev = RTE_BUS_DEVICE(dev, *adev);
- int ret;
-
- ret = rte_auxiliary_driver_remove_dev(adev);
- if (ret == 0) {
- rte_bus_remove_device(&auxiliary_bus, &adev->device);
- rte_devargs_remove(dev->devargs);
- rte_intr_instance_free(adev->intr_handle);
- free(adev);
- }
- return ret;
-}
-
static int
auxiliary_cleanup(void)
{
@@ -206,13 +188,17 @@ auxiliary_cleanup(void)
RTE_BUS_FOREACH_DEV(dev, &auxiliary_bus) {
int ret;
- if (!rte_dev_is_probed(&dev->device))
- continue;
- ret = auxiliary_unplug(&dev->device);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
+ if (rte_dev_is_probed(&dev->device)) {
+ ret = auxiliary_unplug_device(&dev->device);
+ if (ret < 0) {
+ rte_errno = errno;
+ error = -1;
+ }
}
+
+ rte_devargs_remove(dev->device.devargs);
+ rte_bus_remove_device(&auxiliary_bus, &dev->device);
+ free(dev);
}
return error;
@@ -265,7 +251,7 @@ struct rte_bus auxiliary_bus = {
.find_device = rte_bus_generic_find_device,
.match = auxiliary_bus_match,
.probe_device = auxiliary_probe_device,
- .unplug = auxiliary_unplug,
+ .unplug_device = auxiliary_unplug_device,
.parse = auxiliary_parse,
.dma_map = auxiliary_dma_map,
.dma_unmap = auxiliary_dma_unmap,
diff --git a/drivers/bus/cdx/cdx.c b/drivers/bus/cdx/cdx.c
index 2443161e1a..c0b46a41ad 100644
--- a/drivers/bus/cdx/cdx.c
+++ b/drivers/bus/cdx/cdx.c
@@ -374,14 +374,11 @@ rte_cdx_unregister(struct rte_cdx_driver *driver)
rte_bus_remove_driver(&rte_cdx_bus, &driver->driver);
}
-/*
- * If vendor/device ID match, call the remove() function of the
- * driver.
- */
static int
-cdx_detach_dev(struct rte_cdx_device *dev)
+cdx_unplug_device(struct rte_device *rte_dev)
{
- const struct rte_cdx_driver *dr = RTE_BUS_DRIVER(dev->device.driver, *dr);
+ const struct rte_cdx_driver *dr = RTE_BUS_DRIVER(rte_dev->driver, *dr);
+ struct rte_cdx_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
int ret = 0;
CDX_BUS_DEBUG("detach device %s using driver: %s",
@@ -393,9 +390,6 @@ cdx_detach_dev(struct rte_cdx_device *dev)
return ret;
}
- /* clear driver structure */
- dev->device.driver = NULL;
-
rte_cdx_unmap_device(dev);
rte_intr_instance_free(dev->intr_handle);
@@ -404,21 +398,6 @@ cdx_detach_dev(struct rte_cdx_device *dev)
return 0;
}
-static int
-cdx_unplug(struct rte_device *dev)
-{
- struct rte_cdx_device *cdx_dev = RTE_BUS_DEVICE(dev, *cdx_dev);
- int ret;
-
- ret = cdx_detach_dev(cdx_dev);
- if (ret == 0) {
- rte_bus_remove_device(&rte_cdx_bus, &cdx_dev->device);
- rte_devargs_remove(dev->devargs);
- free(cdx_dev);
- }
- return ret;
-}
-
static int
cdx_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
{
@@ -452,7 +431,7 @@ static struct rte_bus rte_cdx_bus = {
.find_device = rte_bus_generic_find_device,
.match = cdx_bus_match,
.probe_device = cdx_probe_device,
- .unplug = cdx_unplug,
+ .unplug_device = cdx_unplug_device,
.parse = cdx_parse,
.dma_map = cdx_dma_map,
.dma_unmap = cdx_dma_unmap,
diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c
index fdc8bcb276..15164796ec 100644
--- a/drivers/bus/fslmc/fslmc_bus.c
+++ b/drivers/bus/fslmc/fslmc_bus.c
@@ -519,7 +519,7 @@ fslmc_bus_probe_device(struct rte_driver *driver, struct rte_device *rte_dev)
}
static int
-fslmc_bus_unplug(struct rte_device *rte_dev)
+fslmc_bus_unplug_device(struct rte_device *rte_dev)
{
struct rte_dpaa2_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
const struct rte_dpaa2_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
@@ -528,7 +528,6 @@ fslmc_bus_unplug(struct rte_device *rte_dev)
drv->remove(dev);
rte_intr_instance_free(dev->intr_handle);
dev->intr_handle = NULL;
- dev->device.driver = NULL;
DPAA2_BUS_INFO("%s Un-Plugged", dev->device.name);
return 0;
}
@@ -546,7 +545,7 @@ struct rte_bus rte_fslmc_bus = {
.get_iommu_class = rte_dpaa2_get_iommu_class,
.match = fslmc_bus_match,
.probe_device = fslmc_bus_probe_device,
- .unplug = fslmc_bus_unplug,
+ .unplug_device = fslmc_bus_unplug_device,
.dev_iterate = rte_bus_generic_dev_iterate,
};
diff --git a/drivers/bus/ifpga/ifpga_bus.c b/drivers/bus/ifpga/ifpga_bus.c
index 2c22329f65..394b777916 100644
--- a/drivers/bus/ifpga/ifpga_bus.c
+++ b/drivers/bus/ifpga/ifpga_bus.c
@@ -276,6 +276,25 @@ ifpga_probe_device(struct rte_driver *drv, struct rte_device *dev)
return afu_drv->probe(afu_dev);
}
+static int
+ifpga_unplug_device(struct rte_device *dev)
+{
+ const struct rte_afu_driver *afu_drv = RTE_BUS_DRIVER(dev->driver, *afu_drv);
+ struct rte_afu_device *afu_dev = RTE_BUS_DEVICE(dev, *afu_dev);
+ int ret = 0;
+
+ if (afu_drv->remove) {
+ ret = afu_drv->remove(afu_dev);
+ if (ret)
+ return ret;
+ }
+
+ rte_intr_instance_free(afu_dev->intr_handle);
+ afu_dev->intr_handle = NULL;
+
+ return 0;
+}
+
/*
* Cleanup the content of the Intel FPGA bus, and call the remove() function
* for all registered devices.
@@ -287,52 +306,24 @@ ifpga_cleanup(void)
int error = 0;
RTE_BUS_FOREACH_DEV(afu_dev, &rte_ifpga_bus) {
- const struct rte_afu_driver *drv;
int ret = 0;
- if (!rte_dev_is_probed(&afu_dev->device))
- goto free;
- drv = RTE_BUS_DRIVER(afu_dev->device.driver, *drv);
- if (drv->remove == NULL)
- goto free;
-
- ret = drv->remove(afu_dev);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
+ if (rte_dev_is_probed(&afu_dev->device)) {
+ ret = ifpga_unplug_device(&afu_dev->device);
+ if (ret < 0) {
+ rte_errno = errno;
+ error = -1;
+ }
}
- afu_dev->device.driver = NULL;
-free:
- rte_bus_remove_device(&rte_ifpga_bus, &afu_dev->device);
rte_devargs_remove(afu_dev->device.devargs);
- rte_intr_instance_free(afu_dev->intr_handle);
+ rte_bus_remove_device(&rte_ifpga_bus, &afu_dev->device);
free(afu_dev);
}
return error;
}
-static int
-ifpga_unplug(struct rte_device *dev)
-{
- struct rte_afu_device *afu_dev = RTE_BUS_DEVICE(dev, *afu_dev);
- const struct rte_afu_driver *afu_drv = RTE_BUS_DRIVER(dev->driver, *afu_drv);
- int ret;
-
- ret = afu_drv->remove(afu_dev);
- if (ret)
- return ret;
-
- rte_bus_remove_device(&rte_ifpga_bus, &afu_dev->device);
-
- rte_devargs_remove(dev->devargs);
- rte_intr_instance_free(afu_dev->intr_handle);
- free(afu_dev);
- return 0;
-
-}
-
static int
ifpga_parse(const char *name, void *addr)
{
@@ -384,7 +375,7 @@ static struct rte_bus rte_ifpga_bus = {
.find_device = rte_bus_generic_find_device,
.match = ifpga_bus_match,
.probe_device = ifpga_probe_device,
- .unplug = ifpga_unplug,
+ .unplug_device = ifpga_unplug_device,
.parse = ifpga_parse,
};
diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c
index 791e9a7b49..bf4822f7ec 100644
--- a/drivers/bus/pci/pci_common.c
+++ b/drivers/bus/pci/pci_common.c
@@ -282,13 +282,10 @@ pci_probe_device(struct rte_driver *drv, struct rte_device *dev)
return ret;
}
-/*
- * If vendor/device ID match, call the remove() function of the
- * driver.
- */
static int
-rte_pci_detach_dev(struct rte_pci_device *dev)
+pci_unplug_device(struct rte_device *rte_dev)
{
+ struct rte_pci_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
struct rte_pci_addr *loc;
const struct rte_pci_driver *dr = RTE_BUS_DRIVER(dev->device.driver, *dr);
int ret = 0;
@@ -308,9 +305,6 @@ rte_pci_detach_dev(struct rte_pci_device *dev)
return ret;
}
- /* clear driver structure */
- dev->device.driver = NULL;
-
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
/* unmap resources for devices that use igb_uio */
rte_pci_unmap_device(dev);
@@ -330,33 +324,17 @@ pci_cleanup(void)
int error = 0;
RTE_BUS_FOREACH_DEV(dev, &rte_pci_bus) {
- const struct rte_pci_driver *drv;
int ret = 0;
- if (!rte_dev_is_probed(&dev->device))
- goto free;
- drv = RTE_BUS_DRIVER(dev->device.driver, *drv);
- if (drv->remove == NULL)
- goto free;
-
- ret = drv->remove(dev);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
+ if (rte_dev_is_probed(&dev->device)) {
+ ret = pci_unplug_device(&dev->device);
+ if (ret < 0) {
+ rte_errno = errno;
+ error = -1;
+ }
}
- if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
- rte_pci_unmap_device(dev);
-
- dev->device.driver = NULL;
-
-free:
- /* free interrupt handles */
- rte_intr_instance_free(dev->intr_handle);
- dev->intr_handle = NULL;
- rte_intr_instance_free(dev->vfio_req_intr_handle);
- dev->vfio_req_intr_handle = NULL;
-
+ rte_devargs_remove(dev->device.devargs);
rte_bus_remove_device(&rte_pci_bus, &dev->device);
pci_free(RTE_PCI_DEVICE_INTERNAL(dev));
}
@@ -521,21 +499,6 @@ pci_sigbus_handler(const void *failure_addr)
return ret;
}
-static int
-pci_unplug(struct rte_device *dev)
-{
- struct rte_pci_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
- int ret;
-
- ret = rte_pci_detach_dev(pdev);
- if (ret == 0) {
- rte_bus_remove_device(&rte_pci_bus, &pdev->device);
- rte_devargs_remove(dev->devargs);
- pci_free(RTE_PCI_DEVICE_INTERNAL(pdev));
- }
- return ret;
-}
-
static int
pci_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
{
@@ -784,7 +747,7 @@ struct rte_bus rte_pci_bus = {
.find_device = rte_bus_generic_find_device,
.match = pci_bus_match,
.probe_device = pci_probe_device,
- .unplug = pci_unplug,
+ .unplug_device = pci_unplug_device,
.parse = pci_parse,
.dev_compare = pci_dev_compare,
.devargs_parse = rte_pci_devargs_parse,
diff --git a/drivers/bus/platform/platform.c b/drivers/bus/platform/platform.c
index 170a2e03d0..5b3c78a505 100644
--- a/drivers/bus/platform/platform.c
+++ b/drivers/bus/platform/platform.c
@@ -416,19 +416,15 @@ device_release_driver(struct rte_platform_device *pdev)
if (ret)
PLATFORM_LOG_LINE(WARNING, "failed to remove %s", pdev->name);
}
-
- pdev->device.driver = NULL;
}
static int
-platform_bus_unplug(struct rte_device *dev)
+platform_bus_unplug_device(struct rte_device *dev)
{
struct rte_platform_device *pdev = RTE_BUS_DEVICE(dev, *pdev);
device_release_driver(pdev);
device_cleanup(pdev);
- rte_devargs_remove(pdev->device.devargs);
- free(pdev);
return 0;
}
@@ -501,10 +497,12 @@ platform_bus_cleanup(void)
struct rte_platform_device *pdev;
RTE_BUS_FOREACH_DEV(pdev, &platform_bus) {
+ if (rte_dev_is_probed(&pdev->device))
+ platform_bus_unplug_device(&pdev->device);
+
+ rte_devargs_remove(pdev->device.devargs);
rte_bus_remove_device(&platform_bus, &pdev->device);
- if (!rte_dev_is_probed(&pdev->device))
- continue;
- platform_bus_unplug(&pdev->device);
+ free(pdev);
}
return 0;
@@ -516,7 +514,7 @@ static struct rte_bus platform_bus = {
.find_device = rte_bus_generic_find_device,
.match = platform_bus_match,
.probe_device = platform_bus_probe_device,
- .unplug = platform_bus_unplug,
+ .unplug_device = platform_bus_unplug_device,
.parse = platform_bus_parse,
.dma_map = platform_bus_dma_map,
.dma_unmap = platform_bus_dma_unmap,
diff --git a/drivers/bus/uacce/uacce.c b/drivers/bus/uacce/uacce.c
index 8a3c55b248..bfe1f26557 100644
--- a/drivers/bus/uacce/uacce.c
+++ b/drivers/bus/uacce/uacce.c
@@ -385,40 +385,10 @@ uacce_probe_device(struct rte_driver *drv, struct rte_device *dev)
}
static int
-uacce_cleanup(void)
+uacce_unplug_device(struct rte_device *rte_dev)
{
- struct rte_uacce_device *dev;
- int error = 0;
-
- RTE_BUS_FOREACH_DEV(dev, &uacce_bus) {
- const struct rte_uacce_driver *dr;
- int ret = 0;
-
- if (!rte_dev_is_probed(&dev->device))
- goto free;
- dr = RTE_BUS_DRIVER(dev->device.driver, *dr);
- if (dr->remove == NULL)
- goto free;
-
- ret = dr->remove(dev);
- if (ret < 0) {
- rte_errno = errno;
- error = -1;
- }
- dev->device.driver = NULL;
-
-free:
- rte_bus_remove_device(&uacce_bus, &dev->device);
- free(dev);
- }
-
- return error;
-}
-
-static int
-uacce_detach_dev(struct rte_uacce_device *dev)
-{
- const struct rte_uacce_driver *dr = RTE_BUS_DRIVER(dev->device.driver, *dr);
+ const struct rte_uacce_driver *dr = RTE_BUS_DRIVER(rte_dev->driver, *dr);
+ struct rte_uacce_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
int ret = 0;
UACCE_BUS_DEBUG("detach device %s using driver: %s", dev->device.name, dr->driver.name);
@@ -429,25 +399,32 @@ uacce_detach_dev(struct rte_uacce_device *dev)
return ret;
}
- dev->device.driver = NULL;
-
return 0;
}
static int
-uacce_unplug(struct rte_device *dev)
+uacce_cleanup(void)
{
- struct rte_uacce_device *uacce_dev = RTE_BUS_DEVICE(dev, *uacce_dev);
- int ret;
+ struct rte_uacce_device *dev;
+ int error = 0;
- ret = uacce_detach_dev(uacce_dev);
- if (ret == 0) {
- rte_bus_remove_device(&uacce_bus, &uacce_dev->device);
- rte_devargs_remove(dev->devargs);
- free(uacce_dev);
+ RTE_BUS_FOREACH_DEV(dev, &uacce_bus) {
+ int ret = 0;
+
+ if (rte_dev_is_probed(&dev->device)) {
+ ret = uacce_unplug_device(&dev->device);
+ if (ret < 0) {
+ rte_errno = errno;
+ error = -1;
+ }
+ }
+
+ rte_devargs_remove(dev->device.devargs);
+ rte_bus_remove_device(&uacce_bus, &dev->device);
+ free(dev);
}
- return ret;
+ return error;
}
static int
@@ -577,7 +554,7 @@ static struct rte_bus uacce_bus = {
.cleanup = uacce_cleanup,
.match = uacce_bus_match,
.probe_device = uacce_probe_device,
- .unplug = uacce_unplug,
+ .unplug_device = uacce_unplug_device,
.find_device = rte_bus_generic_find_device,
.parse = uacce_parse,
.dev_iterate = rte_bus_generic_dev_iterate,
diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
index 673e8a73b2..c2cd642119 100644
--- a/drivers/bus/vdev/vdev.c
+++ b/drivers/bus/vdev/vdev.c
@@ -342,19 +342,15 @@ rte_vdev_init(const char *name, const char *args)
}
static int
-vdev_remove_driver(struct rte_vdev_device *dev)
+vdev_unplug_device(struct rte_device *rte_dev)
{
- const char *name = rte_vdev_device_name(dev);
- const struct rte_vdev_driver *driver;
+ const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(rte_dev->driver, *driver);
+ struct rte_vdev_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
- if (!dev->device.driver) {
- VDEV_LOG(DEBUG, "no driver attach to device %s", name);
- return 1;
- }
+ if (driver->remove)
+ return driver->remove(dev);
- driver = RTE_BUS_DRIVER(dev->device.driver, *driver);
-
- return driver->remove(dev);
+ return 0;
}
RTE_EXPORT_SYMBOL(rte_vdev_uninit)
@@ -375,7 +371,12 @@ rte_vdev_uninit(const char *name)
goto unlock;
}
- ret = vdev_remove_driver(dev);
+ if (rte_dev_is_probed(&dev->device)) {
+ ret = vdev_unplug_device(&dev->device);
+ } else {
+ VDEV_LOG(DEBUG, "no driver attach to device %s", name);
+ ret = 1;
+ }
if (ret)
goto unlock;
@@ -552,27 +553,21 @@ vdev_cleanup(void)
struct rte_vdev_device *dev;
int error = 0;
+ rte_spinlock_recursive_lock(&vdev_device_list_lock);
RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
- const struct rte_vdev_driver *drv;
int ret;
- if (!rte_dev_is_probed(&dev->device))
- goto free;
-
- drv = RTE_BUS_DRIVER(dev->device.driver, *drv);
-
- if (drv->remove == NULL)
- goto free;
-
- ret = drv->remove(dev);
- if (ret < 0)
- error = -1;
+ if (rte_dev_is_probed(&dev->device)) {
+ ret = vdev_unplug_device(&dev->device);
+ if (ret < 0)
+ error = -1;
+ }
- dev->device.driver = NULL;
-free:
+ rte_devargs_remove(dev->device.devargs);
rte_bus_remove_device(&rte_vdev_bus, &dev->device);
free(dev);
}
+ rte_spinlock_recursive_unlock(&vdev_device_list_lock);
return error;
}
@@ -590,12 +585,6 @@ vdev_find_device(const struct rte_bus *bus, const struct rte_device *start,
return dev;
}
-static int
-vdev_unplug(struct rte_device *dev)
-{
- return rte_vdev_uninit(dev->name);
-}
-
static enum rte_iova_mode
vdev_get_iommu_class(void)
{
@@ -622,7 +611,7 @@ static struct rte_bus rte_vdev_bus = {
.find_device = vdev_find_device,
.match = vdev_bus_match,
.probe_device = vdev_probe_device,
- .unplug = vdev_unplug,
+ .unplug_device = vdev_unplug_device,
.parse = vdev_parse,
.dma_map = vdev_dma_map,
.dma_unmap = vdev_dma_unmap,
diff --git a/lib/eal/common/eal_common_dev.c b/lib/eal/common/eal_common_dev.c
index 2a2103ec57..762ed09e21 100644
--- a/lib/eal/common/eal_common_dev.c
+++ b/lib/eal/common/eal_common_dev.c
@@ -385,19 +385,21 @@ local_dev_remove(struct rte_device *dev)
{
int ret;
- if (dev->bus->unplug == NULL) {
- EAL_LOG(ERR, "Function unplug not supported by bus (%s)",
+ if (dev->bus->unplug_device == NULL) {
+ EAL_LOG(ERR, "Function unplug_device not supported by bus (%s)",
dev->bus->name);
return -ENOTSUP;
}
- ret = dev->bus->unplug(dev);
+ ret = dev->bus->unplug_device(dev);
if (ret) {
EAL_LOG(ERR, "Driver cannot detach the device (%s)",
dev->name);
return (ret < 0) ? ret : -ENOENT;
}
+ dev->driver = NULL;
+
return 0;
}
diff --git a/lib/eal/include/bus_driver.h b/lib/eal/include/bus_driver.h
index 0a7e23d98d..1baf024539 100644
--- a/lib/eal/include/bus_driver.h
+++ b/lib/eal/include/bus_driver.h
@@ -114,7 +114,7 @@ typedef int (*rte_bus_probe_device_t)(struct rte_driver *drv, struct rte_device
* 0 on success.
* !0 on error.
*/
-typedef int (*rte_bus_unplug_t)(struct rte_device *dev);
+typedef int (*rte_bus_unplug_device_t)(struct rte_device *dev);
/**
* Bus specific parsing function.
@@ -336,7 +336,7 @@ struct rte_bus {
rte_bus_find_device_t find_device; /**< Find a device on the bus */
rte_bus_match_t match; /**< Check if driver matches device */
rte_bus_probe_device_t probe_device; /**< Probe single device with driver */
- rte_bus_unplug_t unplug; /**< Remove single device from driver */
+ rte_bus_unplug_device_t unplug_device; /**< Remove single device from driver */
rte_bus_parse_t parse; /**< Parse a device name */
rte_bus_dev_compare_t dev_compare; /**< Compare two device names */
rte_bus_devargs_parse_t devargs_parse; /**< Parse bus devargs */
--
2.53.0
^ permalink raw reply related
* [PATCH 08/13] bus/vmbus: allocate interrupt during probing
From: David Marchand @ 2026-06-11 9:45 UTC (permalink / raw)
To: dev; +Cc: thomas, stephen, bruce.richardson, fengchengwen, Long Li, Wei Hu
In-Reply-To: <20260611094551.1514962-1-david.marchand@redhat.com>
Allocating the interrupt handle is a waste of memory if no device is
probed later (like for example, if a allowlist is passed).
Instead, allocate this handle at the time probe_device is called.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
drivers/bus/vmbus/linux/vmbus_bus.c | 6 ------
drivers/bus/vmbus/vmbus_common.c | 18 +++++++++++++++++-
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/bus/vmbus/linux/vmbus_bus.c b/drivers/bus/vmbus/linux/vmbus_bus.c
index 0af10f6a69..77d904ad6d 100644
--- a/drivers/bus/vmbus/linux/vmbus_bus.c
+++ b/drivers/bus/vmbus/linux/vmbus_bus.c
@@ -345,12 +345,6 @@ vmbus_scan_one(const char *name)
}
}
- /* Allocate interrupt handle instance */
- dev->intr_handle =
- rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
- if (dev->intr_handle == NULL)
- goto error;
-
/* device is valid, add in list (sorted) */
VMBUS_LOG(DEBUG, "Adding vmbus device %s", name);
diff --git a/drivers/bus/vmbus/vmbus_common.c b/drivers/bus/vmbus/vmbus_common.c
index 74c1ddff69..b6ae82915f 100644
--- a/drivers/bus/vmbus/vmbus_common.c
+++ b/drivers/bus/vmbus/vmbus_common.c
@@ -108,11 +108,27 @@ vmbus_probe_device(struct rte_driver *drv, struct rte_device *dev)
if (vmbus_dev->device.numa_node < 0 && rte_socket_count() > 1)
VMBUS_LOG(INFO, "Device %s is not NUMA-aware", guid);
+ /* Allocate interrupt handle instance */
+ vmbus_dev->intr_handle =
+ rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
+ if (vmbus_dev->intr_handle == NULL) {
+ ret = -ENOMEM;
+ goto unmap;
+ }
+
/* call the driver probe() function */
VMBUS_LOG(INFO, " probe driver: %s", vmbus_drv->driver.name);
ret = vmbus_drv->probe(vmbus_drv, vmbus_dev);
if (ret != 0)
- rte_vmbus_unmap_device(vmbus_dev);
+ goto free_intr;
+
+ return 0;
+
+free_intr:
+ rte_intr_instance_free(vmbus_dev->intr_handle);
+ vmbus_dev->intr_handle = NULL;
+unmap:
+ rte_vmbus_unmap_device(vmbus_dev);
return ret;
}
--
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