DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Bruce Richardson <bruce.richardson@intel.com>
To: David Marchand <david.marchand@redhat.com>
Cc: <dev@dpdk.org>, <thomas@monjalon.net>,
	<stephen@networkplumber.org>, <fengchengwen@huawei.com>,
	<longli@microsoft.com>, <hemant.agrawal@nxp.com>,
	Parav Pandit <parav@nvidia.com>, Xueming Li <xuemingl@nvidia.com>,
	"Nipun Gupta" <nipun.gupta@amd.com>,
	Nikhil Agarwal <nikhil.agarwal@amd.com>,
	"Sachin Saxena" <sachin.saxena@nxp.com>,
	Rosen Xu <rosen.xu@altera.com>, Chenbo Xia <chenbox@nvidia.com>,
	Tomasz Duszynski <tduszynski@marvell.com>
Subject: Re: [PATCH v2 07/10] bus: align unplug with device probe
Date: Mon, 22 Jun 2026 11:19:00 +0100	[thread overview]
Message-ID: <ajkMFMirIOUtpF1-@bricha3-mobl1.ger.corp.intel.com> (raw)
In-Reply-To: <20260618152826.490569-8-david.marchand@redhat.com>

On Thu, Jun 18, 2026 at 05:28:22PM +0200, David Marchand wrote:
> 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>

Running an AI correctness review reports a potential issue with ifpga bus
after this patch. Maybe worth a double check.

/Bruce

In ifpga_alloc_afu_dev (called at scan time, before any probe),
afu_dev->intr_handle is allocated unconditionally.

In the old ifpga_cleanup, the "goto free:" label ran for all devices, so
intr_handle was freed unconditionally. In the new ifpga_cleanup,
intr_handle is only freed via ifpga_unplug_device, which is only called
when rte_dev_is_probed() returns true. For any ifpga device discovered
during scan but never successfully probed (no matching driver, failed
probe, blocked devargs), intr_handle is leaked. The fix should free it
unconditionally in ifpga_cleanup, outside the rte_dev_is_probed block.

> ---
>  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            |  7 +--
>  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, 129 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 c7549a361a..dca4c5b182 100644
> --- a/drivers/bus/fslmc/fslmc_bus.c
> +++ b/drivers/bus/fslmc/fslmc_bus.c
> @@ -520,6 +520,7 @@ fslmc_bus_probe_device(struct rte_driver *driver, struct rte_device *rte_dev)
>  		return 0;
>  	}
>  
> +	/* FIXME: probe_device should allocate intr_handle */
>  	ret = drv->probe(drv, dev);
>  	if (ret != 0) {
>  		DPAA2_BUS_ERR("Unable to probe");
> @@ -531,7 +532,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);
> @@ -540,7 +541,7 @@ fslmc_bus_unplug(struct rte_device *rte_dev)
>  		int ret = drv->remove(dev);
>  		if (ret != 0)
>  			return ret;
> -		dev->device.driver = NULL;
> +		/* FIXME: unplug_device should free intr_handle */
>  		DPAA2_BUS_INFO("%s Un-Plugged",  dev->device.name);
>  		return 0;
>  	}
> @@ -558,7 +559,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 09221ccdea..7e94f86e28 100644
> --- a/drivers/bus/vdev/vdev.c
> +++ b/drivers/bus/vdev/vdev.c
> @@ -343,19 +343,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)
> @@ -376,7 +372,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;
>  
> @@ -553,27 +554,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;
>  }
> @@ -591,12 +586,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)
>  {
> @@ -623,7 +612,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 9711e6712b..fde55ff06d 100644
> --- a/lib/eal/include/bus_driver.h
> +++ b/lib/eal/include/bus_driver.h
> @@ -101,7 +101,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.
> @@ -323,7 +323,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
> 

  reply	other threads:[~2026-06-22 10:19 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-11  9:45 [PATCH 00/13] Bus cleanup infrastructure and fixes David Marchand
2026-06-11  9:45 ` [PATCH 01/13] bus: fix reference to plug callback David Marchand
2026-06-11  9:45 ` [PATCH 02/13] dma/idxd: remove next pointer in bus specific device David Marchand
2026-06-11  9:45 ` [PATCH 03/13] bus/vdev: remove driver setting in probe David Marchand
2026-06-11  9:45 ` [PATCH 04/13] drivers/bus: cleanup device freeing in NXP bus David Marchand
2026-06-11  9:45 ` [PATCH 05/13] drivers/bus: allocate interrupt during probing " David Marchand
2026-06-11  9:45 ` [PATCH 06/13] bus/pci: fix mapping leak in bus cleanup David Marchand
2026-06-11  9:45 ` [PATCH 07/13] bus/vmbus: fix interrupt leak in cleanup David Marchand
2026-06-11  9:45 ` [PATCH 08/13] bus/vmbus: allocate interrupt during probing David Marchand
2026-06-15 19:13   ` [EXTERNAL] " Long Li
2026-06-11  9:45 ` [PATCH 09/13] bus: align unplug with device probe David Marchand
2026-06-11  9:45 ` [PATCH 10/13] bus: implement cleanup in EAL David Marchand
2026-06-11  9:45 ` [PATCH 11/13] bus/dpaa: support unplug David Marchand
2026-06-11  9:45 ` [PATCH 12/13] bus/vmbus: store name in bus specific device David Marchand
2026-06-11  9:45 ` [PATCH 13/13] bus/vmbus: support unplug David Marchand
2026-06-11 10:09 ` [PATCH 00/13] Bus cleanup infrastructure and fixes David Marchand
2026-06-15 19:14 ` [EXTERNAL] " Long Li
2026-06-15 23:55   ` Long Li
2026-06-16  6:55     ` David Marchand
2026-06-16  7:47       ` David Marchand
2026-06-17  9:16         ` Hemant Agrawal
2026-06-18  8:39           ` David Marchand
2026-06-18 15:28             ` David Marchand
2026-06-18 15:28 ` [PATCH v2 00/10] " David Marchand
2026-06-18 15:28   ` [PATCH v2 01/10] bus: fix reference to plug callback David Marchand
2026-06-22  9:49     ` Bruce Richardson
2026-06-18 15:28   ` [PATCH v2 02/10] dma/idxd: remove next pointer in bus specific device David Marchand
2026-06-22  9:48     ` Bruce Richardson
2026-06-18 15:28   ` [PATCH v2 03/10] bus/vdev: remove driver setting in probe David Marchand
2026-06-18 15:28   ` [PATCH v2 04/10] bus/pci: fix mapping leak in bus cleanup David Marchand
2026-06-18 15:28   ` [PATCH v2 05/10] bus/vmbus: fix interrupt leak in cleanup David Marchand
2026-06-19 22:04     ` [EXTERNAL] " Long Li
2026-06-18 15:28   ` [PATCH v2 06/10] bus/vmbus: allocate interrupt during probing David Marchand
2026-06-19 22:05     ` [EXTERNAL] " Long Li
2026-06-18 15:28   ` [PATCH v2 07/10] bus: align unplug with device probe David Marchand
2026-06-22 10:19     ` Bruce Richardson [this message]
2026-06-22 12:44       ` David Marchand
2026-06-18 15:28   ` [PATCH v2 08/10] bus: implement cleanup in EAL David Marchand
2026-06-22 10:26     ` Bruce Richardson
2026-06-18 15:28   ` [PATCH v2 09/10] bus/vmbus: store name in bus specific device David Marchand
2026-06-22 10:28     ` Bruce Richardson
2026-06-18 15:28   ` [PATCH v2 10/10] bus/vmbus: support unplug David Marchand
2026-06-23 10:54 ` [PATCH v3 00/11] Bus cleanup infrastructure and fixes David Marchand
2026-06-23 10:54   ` [PATCH v3 01/11] bus: fix reference to plug callback David Marchand
2026-06-23 10:54   ` [PATCH v3 02/11] dma/idxd: remove next pointer in bus specific device David Marchand
2026-06-23 10:54   ` [PATCH v3 03/11] bus/vdev: remove driver setting in probe David Marchand
2026-06-23 10:54   ` [PATCH v3 04/11] bus/pci: fix mapping leak in bus cleanup David Marchand
2026-06-23 10:54   ` [PATCH v3 05/11] bus/vmbus: fix interrupt leak in cleanup David Marchand
2026-06-23 10:54   ` [PATCH v3 06/11] bus/vmbus: allocate interrupt during probing David Marchand
2026-06-23 10:54   ` [PATCH v3 07/11] bus/ifpga: " David Marchand
2026-06-23 11:25     ` Bruce Richardson
2026-06-23 10:54   ` [PATCH v3 08/11] bus: align unplug with device probe David Marchand
2026-06-23 10:54   ` [PATCH v3 09/11] bus: implement cleanup in EAL David Marchand
2026-06-23 10:54   ` [PATCH v3 10/11] bus/vmbus: store name in bus specific device David Marchand
2026-06-23 10:54   ` [PATCH v3 11/11] bus/vmbus: support unplug David Marchand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ajkMFMirIOUtpF1-@bricha3-mobl1.ger.corp.intel.com \
    --to=bruce.richardson@intel.com \
    --cc=chenbox@nvidia.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=fengchengwen@huawei.com \
    --cc=hemant.agrawal@nxp.com \
    --cc=longli@microsoft.com \
    --cc=nikhil.agarwal@amd.com \
    --cc=nipun.gupta@amd.com \
    --cc=parav@nvidia.com \
    --cc=rosen.xu@altera.com \
    --cc=sachin.saxena@nxp.com \
    --cc=stephen@networkplumber.org \
    --cc=tduszynski@marvell.com \
    --cc=thomas@monjalon.net \
    --cc=xuemingl@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox