[dpdk-dev] [RFC PATCH 4/6] eal/common: handle bus abstraction for device/driver objects

Shreyansh Jain shreyansh.jain at nxp.com
Thu Nov 17 06:30:03 CET 2016


Primary changes done by this patch are based on:
 - Devices belong to the bus hence the device list is bus instance
   specific
 - Similarly, drivers belong to the bus and thus they too are enclosed
   within the bus instance.
 - All device insertion and driver registration should proceed through
   bus APIs. A new file, eal_common_bus.c has been added for that.

Exiting driver registration and device insert/remove APIs have been
modified to work with bus on which device/driver belong. On the same
lines, the PCI common functions have been modified to work with bus rather
than device/driver directly.

rte_eal_pci_scan is no longer an exposed API. It is part of the bus
implementation. Though, probe continues to be part of the common PCI
operations.

Probe has been split into match and probe. Match has been moved to bus/*
code and is a hook now. EAL code would be modified to handle this hook.

Missing/Grey area:
 - Some API like inserting a device at a particular position in the device
   list are missing. Same for driver. These are needed for cases where
   device update is done rather than addition.
 - Probe is a property of a driver but it should be initiated from a bus,
   for example when added a new device (hotplugging). At present
   rte_driver has the probe hook. This should be wrapped around some API
   at the bus level so that bus can search through multiple drivers
   associated with it for calling probe.

Signed-off-by: Shreyansh Jain <shreyansh.jain at nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c  | 188 ++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_dev.c  |  31 +++--
 lib/librte_eal/common/eal_common_pci.c  | 226 +++++++++++++++++++-------------
 lib/librte_eal/common/include/rte_pci.h |  11 +-
 4 files changed, 342 insertions(+), 114 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..3de1ac7
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,188 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_dev.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+#include <rte_devargs.h>
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	/* XXX all the additions can be address ordered ?
+	 * for example, calling rte_eal_compare_pci_addr and getting <=
+	 * and performing insert a specific location
+	 */
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, dev, next);
+}
+
+/**
+ * Scan all the associated buses
+ */
+int
+rte_eal_bus_scan(void)
+{
+	int ret = 0;
+	struct rte_bus *bus;
+
+	if (TAILQ_EMPTY(&rte_bus_list)) {
+		return 0;
+	}
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for [%s] bus failed.\n",
+				bus->name);
+			continue; /* not a reason to break other bus scan */
+		}
+	}
+
+	/* This function essentially never returns an error - in case of error
+	 * no devices (or limited devices) are available to the application
+	 * which then can fail/report error.
+	 */
+	return 0;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strncmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	/* 3 conditions must meet:
+	 * 1. scan hook should be defined.
+	 * 2. match hook should be defined.
+	 * 3. Name should be a valid string. (valid?)
+	 */
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_HEAD_INITIALIZER(&(bus->driver_list));
+	TAILQ_HEAD_INITIALIZER(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+}
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..bb8d266 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -45,35 +45,44 @@
 
 #include "eal_private.h"
 
-/** Global list of device drivers. */
-static struct rte_driver_list dev_driver_list =
-	TAILQ_HEAD_INITIALIZER(dev_driver_list);
-/** Global list of device drivers. */
-static struct rte_device_list dev_device_list =
-	TAILQ_HEAD_INITIALIZER(dev_device_list);
-
 /* register a driver */
 void
 rte_eal_driver_register(struct rte_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&dev_driver_list, driver, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver && driver->bus);
+	bus = driver->bus;
+	TAILQ_INSERT_TAIL(&(bus->driver_list), driver, next);
 }
 
 /* unregister a driver */
 void
 rte_eal_driver_unregister(struct rte_driver *driver)
 {
-	TAILQ_REMOVE(&dev_driver_list, driver, next);
+	struct rte_bus;
+
+	RTE_VERIFY(driver && driver->bus);
+	bus = driver->bus;
+	TAILQ_REMOVE(&(bus->driver_list), driver, next);
 }
 
 void rte_eal_device_insert(struct rte_device *dev)
 {
-	TAILQ_INSERT_TAIL(&dev_device_list, dev, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev && dev->bus);
+	bus = dev->bus;
+	TAILQ_INSERT_TAIL(&(bus->device_list), dev, next);
 }
 
 void rte_eal_device_remove(struct rte_device *dev)
 {
-	TAILQ_REMOVE(&dev_device_list, dev, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev && dev->bus);
+	bus = dev->bus;
+	TAILQ_REMOVE(&(bus->device_list), dev, next);
 }
 
 int
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 971ad20..7a6d258 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -82,12 +82,13 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
+#define PCI_BUS_NAME "pci_bus"
+
+static struct rte_bus_list pci_bus_list =
+	TAILQ_HEAD_INITIALIZER(pci_bus_list);
+
+struct rte_bus pci_bus;
 
 const char *pci_get_sysfs_path(void)
 {
@@ -160,64 +161,40 @@ static int
 rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
 {
 	int ret;
-	const struct rte_pci_id *id_table;
-
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->class_id != dev->id.class_id &&
-				id_table->class_id != RTE_CLASS_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	struct rte_pci_addr *loc = &dev->addr;
+
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
+		return 1;
+	}
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
 
-		/* reference driver structure */
-		dev->driver = dr;
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* call the driver probe() function */
-		return dr->probe(dr, dev);
-	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	/* call the driver probe() function */
+	return dr->probe(dr, dev);
 }
 
 /*
@@ -284,6 +261,7 @@ static int
 pci_probe_all_drivers(struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_bus *pci_bus;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -293,15 +271,21 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_probe_one_driver(dr, dev);
-		if (rc < 0)
-			/* negative value is an error */
-			return -1;
-		if (rc > 0)
-			/* positive value means driver doesn't support it */
-			continue;
-		return 0;
+	TAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {
+		rc = pci_bus->match(dr, dev);
+		if (!rc) {
+			rc = rte_eal_pci_probe_one_driver(dr, dev);
+			if (rc < 0)
+				/* negative value is an error */
+				return -1;
+			if (rc > 0)
+				/* positive value means driver doesn't support
+				 * it
+				 */
+				continue;
+			return 0;
+		}
+		/* Else, continue to next driver */
 	}
 	return 1;
 }
@@ -314,13 +298,19 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 static int
 pci_detach_all_drivers(struct rte_pci_device *dev)
 {
-	struct rte_pci_driver *dr = NULL;
+	struct rte_pci_driver *pci_drv= NULL;
+	struct rte_driver *drv = NULL;
+	struct rte_bus *pci_bus;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	RTE_VERIFY(dev->device->bus);
+	pci_bus = dev->device->bus;
+
+	TAILQ_FOREACH(drv, &pci_bus->driver_list, next) {
+		pci_drv = container_of(drv, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -340,19 +330,28 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
 int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_bus *pci_bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(DEBUG, EAL, "Unable to find PCI bus\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &pci_bus->device_list, next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -376,22 +375,31 @@ err_return:
 int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct rte_bus *pci_bus = NULL;
+	struct rte_device *dev = NULL;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(DEBUG, EAL, "Unable to find PCI bus\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(dev, &(bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
+		if (rte_eal_compare_pci_addr(&pci_dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(pci_dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		free(dev);
+		TAILQ_REMOVE(&pci_bus->device_list, dev, next);
+		free(pci_dev);
 		return 0;
 	}
 	return -1;
@@ -411,31 +419,42 @@ err_return:
 int
 rte_eal_pci_probe(void)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_bus *pci_bus;
+	struct rte_pci_device *pci_dev;
 	struct rte_devargs *devargs;
 	int probe_all = 0;
 	int ret = 0;
 
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(INFO, EAL, "(%s): No such bus exists\n", PCI_BUS_NAME);
+		/* Cannot continue ahead and this is not an error */
+		return;
+	}
+
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(pci_bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
 
 		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
+		devargs = pci_devargs_lookup(pci_dev);
 		if (devargs != NULL)
-			dev->device.devargs = devargs;
+			pci_dev->device.devargs = devargs;
 
 		/* probe all or only whitelisted devices */
 		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(pci_dev);`
 		else if (devargs != NULL &&
 			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(pci_dev);
 		if (ret < 0)
 			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+				 " cannot be used\n", pci_dev->addr.domain,
+				 pci_dev->addr.bus, pci_dev->addr.devid,
+				 pci_dev->addr.function);
 	}
 
 	return 0;
@@ -465,10 +484,19 @@ pci_dump_one_device(FILE *f, struct rte_pci_device *dev)
 void
 rte_eal_pci_dump(FILE *f)
 {
-	struct rte_pci_device *dev = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		pci_dump_one_device(f, dev);
+	bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!bus) {
+		RTE_LOG(INFO, EAL, "(%s): No such bus exists\n", PCI_BUS_NAME);
+		return;
+	}
+
+	TAILQ_FOREACH(dev, &(bus->device_list), next) {
+		pci_dev = container_of(dev, struct rte_pci_device, device);
+		pci_dump_one_device(f, pci_dev);
 	}
 }
 
@@ -476,7 +504,16 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
+	struct rte_bus *pci_bus;
+
+	pci_bus = rte_eal_get_bus(PCI_BUS_NAME);
+	if (!pci_bus) {
+		RTE_LOG(INFO, EAL, "(%s) No such bus exists\n", PCI_BUS_NAME);
+		return;
+		/* TODO: How to return error from here? */
+	}
+
+	driver->driver->bus = pci_bus;
 	rte_eal_driver_register(&driver->driver);
 }
 
@@ -484,6 +521,9 @@ rte_eal_pci_register(struct rte_pci_driver *driver)
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_bus *pci_bus;
+
+	pci_bus = driver->driver->bus;
+	rte_eal_driver_unregister(&pci_bus, &driver->driver);
+	driver->driver->bus = NULL;
 }
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 9ce8847..cffc449 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -110,7 +110,7 @@ const char *pci_get_sysfs_path(void);
 
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
-
+/
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -360,15 +360,6 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 }
 
 /**
- * Scan the content of the PCI bus, and the devices in the devices
- * list
- *
- * @return
- *  0 on success, negative on error
- */
-int rte_eal_pci_scan(void);
-
-/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
-- 
2.7.4



More information about the dev mailing list