Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Changes to test_pci:
- use a dummy test_pci_bus for all PCI test driver registrations
- this reduces the need for cleaning global list
- add necessary callbacks for invoking scan and probing/matching
  using EAL PCI scan code

Note: With this patch, all PCI PMDs would cease to work because of lack
      rte_driver->probe/remove implementations. Next patch would do that.

Signed-off-by: Shreyansh Jain <shreyansh.j...@nxp.com>
---
 app/test/test_pci.c                             | 154 +++++++++++------
 lib/librte_eal/bsdapp/eal/eal.c                 |   8 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
 lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_pci.h         |  53 +++---
 lib/librte_eal/linuxapp/eal/eal.c               |   8 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
 10 files changed, 332 insertions(+), 240 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index f9b84db..e95b758 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
@@ -61,10 +62,18 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+static struct rte_bus *pci_bus; /* global reference to a Test PCI bus */
 
 static int my_driver_init(struct rte_pci_driver *dr,
                          struct rte_pci_device *dev);
 
+/* Test PCI bus. */
+struct rte_bus test_pci_bus = {
+       .name = "test_pci_bus",
+       .scan = rte_eal_pci_scan,
+       .match = rte_eal_pci_match,
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
        {RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +88,9 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
        .driver = {
-               .name = "test_driver"
+               .name = "test_driver",
+               .probe = rte_eal_pci_probe,
+               .remove = rte_eal_pci_remove,
        },
        .probe = my_driver_init,
        .id_table = my_driver_id,
@@ -88,7 +99,9 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
        .driver = {
-               .name = "test_driver2"
+               .name = "test_driver2",
+               .probe = rte_eal_pci_probe,
+               .remove = rte_eal_pci_remove,
        },
        .probe = my_driver_init,
        .id_table = my_driver_id2,
@@ -108,14 +121,67 @@ my_driver_init(__attribute__((unused)) struct 
rte_pci_driver *dr,
        return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+       int i;
+       struct rte_pci_device *dev = NULL;
+       struct rte_device *r_dev = NULL;
+
+       TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+               dev = container_of(r_dev, struct rte_pci_device, device);
+
+               fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+                      dev->addr.devid, dev->addr.function);
+               fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+                      dev->id.device_id);
+
+               for (i = 0; i != sizeof(dev->mem_resource) /
+                       sizeof(dev->mem_resource[0]); i++) {
+                       fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+                               dev->mem_resource[i].phys_addr,
+                               dev->mem_resource[i].len);
+               }
+       }
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+       int ret;
+       struct rte_device *device;
+       struct rte_driver *driver;
+
+       TAILQ_FOREACH(device, &pci_bus->device_list, next) {
+               TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+                       ret = pci_bus->match(driver, device);
+                       if (!ret) {
+                               if (!driver->probe)
+                                       continue;
+
+                               device->driver = driver;
+                               ret = driver->probe(driver, device);
+                               if (ret != 0)
+                                       return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
        struct rte_pci_device *dev = NULL;
+       struct rte_device *device = NULL;
        unsigned i = 0;
        char pci_addr_str[16];
 
-       TAILQ_FOREACH(dev, &pci_device_list, next) {
+       TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+               dev = container_of(device, struct rte_pci_device, device);
                snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
                        dev->addr.domain, dev->addr.bus, dev->addr.devid,
                        dev->addr.function);
@@ -142,19 +208,11 @@ static void free_devargs_list(void)
        }
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-       TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-       TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-       struct rte_pci_device *dev;
-       struct rte_pci_driver *dr;
        const struct resource *r;
        int ret;
 
@@ -167,22 +225,19 @@ test_pci_setup(void)
        ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
        TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-       /* Unregister original devices & drivers lists */
-       while (!TAILQ_EMPTY(&pci_driver_list)) {
-               dr = TAILQ_FIRST(&pci_driver_list);
-               rte_eal_pci_unregister(dr);
-               TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-       }
+       /* Create a new Bus called 'test_pci_bus' */
+       /* Bus doesn't exist; Create the test bus */
+       printf("Creating a Test PCI bus\n");
+       rte_eal_bus_register(&test_pci_bus);
+       pci_bus = &test_pci_bus;
 
-       while (!TAILQ_EMPTY(&pci_device_list)) {
-               dev = TAILQ_FIRST(&pci_device_list);
-               TAILQ_REMOVE(&pci_device_list, dev, next);
-               TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-       }
+       printf("Scan for Test devices and add to bus\n");
+       ret = pci_bus->scan(pci_bus);
 
-       ret = rte_eal_pci_scan(NULL);
        TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-       rte_eal_pci_dump(stdout);
+
+       printf("Dump of all devices scanned:\n");
+       do_pci_device_dump(stdout);
 
        return 0;
 }
@@ -190,8 +245,8 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-       struct rte_pci_device *dev;
-       struct rte_pci_driver *dr;
+       struct rte_device *dev = NULL;
+       struct rte_driver *dr = NULL;
        const struct resource *r;
        int ret;
 
@@ -203,28 +258,23 @@ test_pci_cleanup(void)
        ret = resource_rm_by_tar(r);
        TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+       TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
        /*
         * FIXME: there is no API in DPDK to free a rte_pci_device so we
         * cannot free the devices in the right way. Let's assume that we
         * don't care for tests.
         */
-       while (!TAILQ_EMPTY(&pci_device_list)) {
-               dev = TAILQ_FIRST(&pci_device_list);
-               TAILQ_REMOVE(&pci_device_list, dev, next);
+       TAILQ_FOREACH(dev, &(pci_bus->device_list), next) {
+               rte_eal_bus_remove_device(dev);
+               dev->driver = NULL;
        }
 
-       /* Restore original devices & drivers lists */
-       while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-               dr = TAILQ_FIRST(&real_pci_driver_list);
-               TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-               rte_eal_pci_register(dr);
+       TAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {
+               rte_eal_bus_remove_driver(dr);
        }
 
-       while (!TAILQ_EMPTY(&real_pci_device_list)) {
-               dev = TAILQ_FIRST(&real_pci_device_list);
-               TAILQ_REMOVE(&real_pci_device_list, dev, next);
-               TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-       }
+       rte_eal_bus_unregister(pci_bus);
 
        return 0;
 }
@@ -234,16 +284,19 @@ test_pci_blacklist(void)
 {
        struct rte_devargs_list save_devargs_list;
 
-       printf("Dump all devices\n");
-       TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-                       "pci_driver_list not empty");
+       TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
+       TEST_ASSERT(TAILQ_EMPTY(&pci_bus->driver_list),
+                   "PCI Driver list not empty");
 
-       rte_eal_pci_register(&my_driver);
-       rte_eal_pci_register(&my_driver2);
+       /* Add test drivers to Bus */
+       rte_eal_bus_add_driver(pci_bus, &(my_driver.driver));
+       rte_eal_bus_add_driver(pci_bus, &(my_driver2.driver));
 
        pci_dev_count = 0;
-       printf("Scan bus\n");
-       rte_eal_pci_probe();
+
+       printf("Probe the Test Bus\n");
+       do_pci_bus_probe();
 
        if (pci_dev_count == 0) {
                printf("no device detected\n");
@@ -257,8 +310,8 @@ test_pci_blacklist(void)
        blacklist_all_devices();
 
        pci_dev_count = 0;
-       printf("Scan bus with all devices blacklisted\n");
-       rte_eal_pci_probe();
+       printf("Probe bus with all devices blacklisted\n");
+       do_pci_bus_probe();
 
        free_devargs_list();
        devargs_list = save_devargs_list;
@@ -270,8 +323,9 @@ test_pci_blacklist(void)
 
        test_pci_run = 1;
 
-       rte_eal_pci_unregister(&my_driver);
-       rte_eal_pci_unregister(&my_driver2);
+       /* Clear the test drivers added to Test Bus */
+       rte_eal_bus_remove_driver(&(my_driver.driver));
+       rte_eal_bus_remove_driver(&(my_driver2.driver));
 
        return 0;
 }
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2c223de..f801076 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_timer_init() < 0)
                rte_panic("Cannot init HPET or TSC timers\n");
 
-       if (rte_eal_pci_init() < 0)
-               rte_panic("Cannot init PCI\n");
-
        eal_check_mem_on_local_socket();
 
        if (eal_plugins_init() < 0)
@@ -613,10 +610,7 @@ rte_eal_init(int argc, char **argv)
        rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
        rte_eal_mp_wait_lcore();
 
-       /* Probe & Initialize PCI devices */
-       if (rte_eal_pci_probe())
-               rte_panic("Cannot probe PCI\n");
-
+       /* Probe all the buses and devices/drivers on them */
        if (rte_eal_bus_probe())
                rte_panic("Cannot probe devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 56b506e..2190d0d 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -240,7 +241,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, 
int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
        struct rte_pci_device *dev;
        struct pci_bar_io bar;
@@ -313,19 +314,23 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
        }
 
        /* device is valid, add in list (sorted) */
-       if (TAILQ_EMPTY(&pci_device_list)) {
-               TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+       if (TAILQ_EMPTY(&bus->device_list)) {
+               rte_eal_bus_add_device(bus, &dev->device);
        }
        else {
                struct rte_pci_device *dev2 = NULL;
+               struct rte_device *r_dev2;
                int ret;
 
-               TAILQ_FOREACH(dev2, &pci_device_list, next) {
+               TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+                       dev2 = container_of(r_dev2, struct rte_pci_device,
+                                           device);
                        ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
                        if (ret > 0)
                                continue;
                        else if (ret < 0) {
-                               TAILQ_INSERT_BEFORE(dev2, dev, next);
+                               rte_eal_bus_insert_device(bus, &dev2->device,
+                                                         &dev->device);
                                return 0;
                        } else { /* already registered */
                                dev2->kdrv = dev->kdrv;
@@ -337,7 +342,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
                                return 0;
                        }
                }
-               TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+               rte_eal_bus_add_device(bus, &dev->device);
        }
 
        return 0;
@@ -352,7 +357,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
        int fd;
        unsigned dev_count = 0;
@@ -365,6 +370,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
                        .matches = &matches[0],
        };
 
+       /* for debug purposes, PCI can be disabled */
+       if (internal_config.no_pci)
+               return 0;
+
        fd = open("/dev/pci", O_RDONLY);
        if (fd < 0) {
                RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -380,7 +389,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
                }
 
                for (i = 0; i < conf_io.num_matches; i++)
-                       if (pci_scan_one(fd, &matches[i]) < 0)
+                       if (pci_scan_one(bus, fd, &matches[i]) < 0)
                                goto error;
 
                dev_count += conf_io.num_matches;
@@ -398,9 +407,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-       int fd;
+       int fd = -1;
        struct pci_conf matches[2];
        struct pci_match_conf match = {
                .pc_sel = {
@@ -418,6 +427,9 @@ pci_update_device(const struct rte_pci_addr *addr)
                .matches = &matches[0],
        };
 
+       if (!bus)
+               goto error;
+
        fd = open("/dev/pci", O_RDONLY);
        if (fd < 0) {
                RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -433,7 +445,7 @@ pci_update_device(const struct rte_pci_addr *addr)
        if (conf_io.num_matches != 1)
                goto error;
 
-       if (pci_scan_one(fd, &matches[0]) < 0)
+       if (pci_scan_one(bus, fd, &matches[0]) < 0)
                goto error;
 
        close(fd);
@@ -659,17 +671,9 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
        return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-       /* for debug purposes, PCI can be disabled */
-       if (internal_config.no_pci)
-               return 0;
+struct rte_bus pci_bus = {
+       .scan = rte_eal_pci_scan,
+       .match = rte_eal_pci_match,
+};
 
-       if (rte_eal_pci_scan(NULL) < 0) {
-               RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-               return -1;
-       }
-       return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 51115f4..4874902 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
        eal_parse_sysfs_value;
        eal_timer_source;
        lcore_config;
-       pci_device_list;
-       pci_driver_list;
        per_lcore__lcore_id;
        per_lcore__rte_errno;
        rte_calloc;
@@ -41,7 +39,6 @@ DPDK_2.0 {
        rte_eal_mp_wait_lcore;
        rte_eal_parse_devargs_str;
        rte_eal_pci_dump;
-       rte_eal_pci_probe;
        rte_eal_pci_probe_one;
        rte_eal_pci_register;
        rte_eal_pci_scan;
@@ -188,5 +185,9 @@ DPDK_17.02 {
        rte_eal_bus_remove_device;
        rte_eal_bus_remove_driver;
        rte_eal_bus_unregister;
+       rte_eal_pci_match;
+       rte_eal_pci_probe;
+       rte_eal_pci_remove;
+       rte_eal_pci_scan;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index b7be6aa..ce19b9a 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -82,11 +83,6 @@
 
 #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"
 
 const char *pci_get_sysfs_path(void)
@@ -206,39 +202,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
                             struct rte_pci_device *dev)
 {
        int ret;
-       struct rte_driver *driver;
-       struct rte_device *device;
-       struct rte_pci_addr *loc;
 
        if ((dr == NULL) || (dev == NULL))
                return -EINVAL;
 
-       driver = &dr->driver;
-       device = &dev->device;
-       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;
-       }
-
-       /* The device is not blacklisted; Check if driver supports it */
-       ret = rte_eal_pci_match(driver, device);
-       if (ret) {
-               /* Match of device and driver failed */
-               RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-                       driver->name);
-               return 1;
-       }
-
        RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
                        dev->id.device_id, dr->driver.name);
 
@@ -271,23 +238,11 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
                struct rte_pci_device *dev)
 {
-       int ret;
-       struct rte_driver *driver = NULL;
-       struct rte_device *device;
        struct rte_pci_addr *loc;
 
        if ((dr == NULL) || (dev == NULL))
                return -EINVAL;
 
-       driver = &(dr->driver);
-       device = &(dev->device);
-
-       ret = rte_eal_pci_match(driver, device);
-       if (ret) {
-               /* Device and driver don't match */
-               return 1;
-       }
-
        loc = &dev->addr;
 
        RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -316,9 +271,9 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
-       struct rte_pci_driver *dr = NULL;
+       struct rte_driver *r_dr = NULL;
        int rc = 0;
 
        if (dev == NULL)
@@ -328,8 +283,8 @@ 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);
+       TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+               rc = rte_eal_pci_probe(r_dr, &dev->device);
                if (rc < 0)
                        /* negative value is an error */
                        return -1;
@@ -347,15 +302,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
        struct rte_pci_driver *dr = NULL;
+       struct rte_driver *r_dr = NULL;
        int rc = 0;
 
        if (dev == NULL)
                return -1;
 
-       TAILQ_FOREACH(dr, &pci_driver_list, next) {
+       TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+               dr = container_of(r_dr, struct rte_pci_driver, driver);
                rc = rte_eal_pci_detach_dev(dr, dev);
                if (rc < 0)
                        /* negative value is an error */
@@ -376,22 +333,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
        struct rte_pci_device *dev = NULL;
+       struct rte_device *r_dev = NULL;
+       struct rte_bus *bus;
        int ret = 0;
 
        if (addr == NULL)
                return -1;
 
+       bus = rte_eal_bus_get("pci");
+       if (!bus) {
+               RTE_LOG(ERR, EAL, "PCI Bus not registered\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)
+       if (pci_update_device(bus, addr) < 0)
                goto err_return;
 
-       TAILQ_FOREACH(dev, &pci_device_list, next) {
+       TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+               dev = container_of(r_dev, struct rte_pci_device, device);
                if (rte_eal_compare_pci_addr(&dev->addr, addr))
                        continue;
 
-               ret = pci_probe_all_drivers(dev);
+               ret = pci_probe_all_drivers(bus, dev);
                if (ret)
                        goto err_return;
                return 0;
@@ -412,20 +378,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
        struct rte_pci_device *dev = NULL;
+       struct rte_device *r_dev = NULL;
+       struct rte_bus *bus;
        int ret = 0;
 
        if (addr == NULL)
                return -1;
 
-       TAILQ_FOREACH(dev, &pci_device_list, next) {
+       bus = rte_eal_bus_get("pci");
+       if (!bus) {
+               RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+               return -1;
+       }
+
+       TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+               dev = container_of(r_dev, struct rte_pci_device, device);
                if (rte_eal_compare_pci_addr(&dev->addr, addr))
                        continue;
 
-               ret = pci_detach_all_drivers(dev);
+               ret = pci_detach_all_drivers(bus, dev);
                if (ret < 0)
                        goto err_return;
 
-               TAILQ_REMOVE(&pci_device_list, dev, next);
+               rte_eal_bus_remove_device(r_dev);
                free(dev);
                return 0;
        }
@@ -438,41 +413,73 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
        return -1;
 }
 
-/*
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
- */
 int
-rte_eal_pci_probe(void)
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)
 {
-       struct rte_pci_device *dev = NULL;
-       struct rte_devargs *devargs;
-       int probe_all = 0;
        int ret = 0;
+       struct rte_devargs *devargs;
+       struct rte_pci_device *pci_dev;
+       struct rte_pci_driver *pci_drv;
+       struct rte_pci_addr *loc;
 
-       if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-               probe_all = 1;
+       if (!driver || !device)
+               return -1;
 
-       TAILQ_FOREACH(dev, &pci_device_list, next) {
+       pci_dev = container_of(device, struct rte_pci_device, device);
+       pci_drv = container_of(driver, struct rte_pci_driver, driver);
 
-               /* set devargs in PCI structure */
-               devargs = pci_devargs_lookup(dev);
-               if (devargs != NULL)
-                       dev->device.devargs = devargs;
+       loc = &pci_dev->addr;
 
-               /* probe all or only whitelisted devices */
-               if (probe_all)
-                       ret = pci_probe_all_drivers(dev);
-               else if (devargs != NULL &&
-                       devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-                       ret = pci_probe_all_drivers(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);
+       RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+                       loc->domain, loc->bus, loc->devid, loc->function,
+                       pci_dev->device.numa_node);
+
+       /* Fetch the devargs associated with the device */
+       devargs = pci_devargs_lookup(pci_dev);
+       if (devargs != NULL)
+               pci_dev->device.devargs = devargs;
+
+       /* no initialization when blacklisted, return without error */
+       if (pci_dev->device.devargs != NULL &&
+           pci_dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+               RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+                       " initializing\n");
+               return 1;
        }
 
+       ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+       if (ret < 0) {
+               RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+                       " cannot be used\n", pci_dev->addr.domain,
+                       pci_dev->addr.bus, pci_dev->addr.devid,
+                       pci_dev->addr.function);
+               return ret;
+       }
+       return 0;
+}
+
+int
+rte_eal_pci_remove(struct rte_device *device)
+{
+       int ret = 0;
+       struct rte_pci_device *pci_dev;
+
+       if (!device)
+               return -1;
+
+       pci_dev = container_of(device, struct rte_pci_device, device);
+
+       if (!pci_dev->driver)
+               return -1;
+
+       ret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);
+       if (ret < 0) {
+               RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+                       " cannot be used\n", pci_dev->addr.domain,
+                       pci_dev->addr.bus, pci_dev->addr.devid,
+                       pci_dev->addr.function);
+               return ret;
+       }
        return 0;
 }
 
@@ -501,8 +508,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
        struct rte_pci_device *dev = NULL;
+       struct rte_device *r_dev = NULL;
+       struct rte_bus *bus;
 
-       TAILQ_FOREACH(dev, &pci_device_list, next) {
+       bus = rte_eal_bus_get("pci");
+       if (!bus) {
+               RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+               return;
+       }
+
+       TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+               dev = container_of(r_dev, struct rte_pci_device, device);
                pci_dump_one_device(f, dev);
        }
 }
@@ -511,14 +527,32 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-       TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-       rte_eal_driver_register(&driver->driver);
+       struct rte_bus *bus;
+
+       RTE_VERIFY(driver);
+
+       bus = rte_eal_bus_get("pci");
+       if (!bus) {
+               RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+               return;
+       }
+
+       rte_eal_bus_add_driver(bus, &driver->driver);
 }
 
 /* unregister a 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 *bus;
+
+       RTE_VERIFY(driver);
+
+       bus = driver->driver.bus;
+       if (!bus) {
+               RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+               return;
+       }
+
+       rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h 
b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..06ec172 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
@@ -126,13 +116,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *     The PCI bus on which device is connected
  * @param addr
  *     The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_pci.h 
b/lib/librte_eal/common/include/rte_pci.h
index e5e58dd..1647672 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI 
drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI 
devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -376,6 +370,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
+ * Probe callback for the PCI bus
+ *
+ * For each matched pair of PCI device and driver on PCI bus, perform devargs
+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances
+ * and intializing them.
+ *
+ * @param driver
+ *     Generic driver object matched with the device
+ * @param device
+ *     Generic device object to initialize
+ * @return
+ *   - 0 on success.
+ *   - !0 on error.
+ */
+int
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);
+
+/**
+ * Remove callback for the PCI bus
+ *
+ * Called when a device needs to be removed from a bus; wraps around the
+ * PCI specific implementation layered over rte_pci_driver->remove. Default
+ * handler used by PCI PMDs
+ *
+ * @param device
+ *     rte_device object referring to device to be removed
+ * @return
+ *     - 0 for successful removal
+ *     - !0 for failure in removal of device
+ */
+int
+rte_eal_pci_remove(struct rte_device *device);
+
+/**
  * Match the PCI Driver and Device using the ID Table
  *
  * @param drv
@@ -390,19 +418,6 @@ int
 rte_eal_pci_match(struct rte_driver *drv, struct rte_device *dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal.c 
b/lib/librte_eal/linuxapp/eal/eal.c
index 1a17891..2a20e90 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
                rte_panic("Cannot init logs\n");
 
-       if (rte_eal_pci_init() < 0)
-               rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
        if (rte_eal_vfio_setup() < 0)
                rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,7 @@ rte_eal_init(int argc, char **argv)
        rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
        rte_eal_mp_wait_lcore();
 
-       /* Probe & Initialize PCI devices */
-       if (rte_eal_pci_probe())
-               rte_panic("Cannot probe PCI\n");
-
+       /* Probe all the buses and devices/drivers on them */
        if (rte_eal_bus_probe())
                rte_panic("Cannot probe devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c 
b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 4a0207d..314effa 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -228,7 +229,8 @@ pci_parse_sysfs_resource(const char *filename, struct 
rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_bus *bus, const char *dirname,
+            const struct rte_pci_addr *addr)
 {
        char filename[PATH_MAX];
        unsigned long tmp;
@@ -346,21 +348,23 @@ pci_scan_one(const char *dirname, const struct 
rte_pci_addr *addr)
                dev->kdrv = RTE_KDRV_NONE;
 
        /* device is valid, add in list (sorted) */
-       if (TAILQ_EMPTY(&pci_device_list)) {
-               rte_eal_device_insert(&dev->device);
-               TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+       if (TAILQ_EMPTY(&bus->device_list)) {
+               rte_eal_bus_add_device(bus, &dev->device);
        } else {
                struct rte_pci_device *dev2;
+               struct rte_device *r_dev2;
                int ret;
 
-               TAILQ_FOREACH(dev2, &pci_device_list, next) {
+               TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+                       dev2 = container_of(r_dev2, struct rte_pci_device,
+                                           device);
                        ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
                        if (ret > 0)
                                continue;
 
                        if (ret < 0) {
-                               TAILQ_INSERT_BEFORE(dev2, dev, next);
-                               rte_eal_device_insert(&dev->device);
+                               rte_eal_bus_insert_device(bus, &dev2->device,
+                                                         &dev->device);
                        } else { /* already registered */
                                dev2->kdrv = dev->kdrv;
                                dev2->max_vfs = dev->max_vfs;
@@ -370,15 +374,14 @@ pci_scan_one(const char *dirname, const struct 
rte_pci_addr *addr)
                        }
                        return 0;
                }
-               rte_eal_device_insert(&dev->device);
-               TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+               rte_eal_bus_add_device(bus, &dev->device);
        }
 
        return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
        char filename[PATH_MAX];
 
@@ -386,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
                 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
                 addr->function);
 
-       return pci_scan_one(filename, addr);
+       return pci_scan_one(bus, filename, addr);
 }
 
 /*
@@ -440,13 +443,22 @@ parse_pci_addr_format(const char *buf, int bufsize, 
struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
        struct dirent *e;
        DIR *dir;
        char dirname[PATH_MAX];
        struct rte_pci_addr addr;
 
+       if (!bus_p) {
+               RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+               return -1;
+       }
+
+       /* for debug purposes, PCI can be disabled */
+       if (internal_config.no_pci)
+               return 0;
+
        dir = opendir(pci_get_sysfs_path());
        if (dir == NULL) {
                RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -465,7 +477,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
                snprintf(dirname, sizeof(dirname), "%s/%s",
                                pci_get_sysfs_path(), e->d_name);
-               if (pci_scan_one(dirname, &addr) < 0)
+               if (pci_scan_one(bus_p, dirname, &addr) < 0)
                        goto error;
        }
        closedir(dir);
@@ -711,18 +723,9 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
        return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-       /* for debug purposes, PCI can be disabled */
-       if (internal_config.no_pci)
-               return 0;
-
-       if (rte_eal_pci_scan(NULL) < 0) {
-               RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-               return -1;
-       }
+struct rte_bus pci_bus = {
+       .scan = rte_eal_pci_scan,
+       .match = rte_eal_pci_match,
+};
 
-       return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map 
b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index abfe93e..239f2fc 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
        eal_parse_sysfs_value;
        eal_timer_source;
        lcore_config;
-       pci_device_list;
-       pci_driver_list;
        per_lcore__lcore_id;
        per_lcore__rte_errno;
        rte_calloc;
@@ -41,7 +39,6 @@ DPDK_2.0 {
        rte_eal_mp_wait_lcore;
        rte_eal_parse_devargs_str;
        rte_eal_pci_dump;
-       rte_eal_pci_probe;
        rte_eal_pci_probe_one;
        rte_eal_pci_register;
        rte_eal_pci_scan;
@@ -192,5 +189,9 @@ DPDK_17.02 {
        rte_eal_bus_remove_device;
        rte_eal_bus_remove_driver;
        rte_eal_bus_unregister;
+       rte_eal_pci_match;
+       rte_eal_pci_probe;
+       rte_eal_pci_remove;
+       rte_eal_pci_scan;
 
 } DPDK_16.11;
-- 
2.7.4

Reply via email to