[PATCH 10/13] bus: implement cleanup in EAL
David Marchand
david.marchand at redhat.com
Thu Jun 11 11:45:47 CEST 2026
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 at 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
More information about the dev
mailing list