new file mode 100644
@@ -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);
+}
@@ -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
@@ -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;
}
@@ -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