[dpdk-dev] [PATCH v5 10/12] eal: enable PCI bus and PCI test framework
Shreyansh Jain
shreyansh.jain at nxp.com
Mon Dec 26 14:24:03 CET 2016
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.jain at 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
More information about the dev
mailing list