X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_pci.c;h=72547bd28569c080af69b909f0797ffc51b4dd34;hb=2eed820fd4fdea456103402e0ad13f955321e6cc;hp=c0be2929d937db35de16c5bed00cfeee137d46dd;hpb=35b3313e322b28a293eaaddf362844f934b9f436;p=dpdk.git diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index c0be2929d9..72547bd285 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -82,8 +82,23 @@ #include "eal_private.h" -struct pci_driver_list pci_driver_list; -struct pci_device_list pci_device_list; +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) +{ + const char *path = NULL; + + path = getenv("SYSFS_PCI_DEVICES"); + if (path == NULL) + return SYSFS_PCI_DEVICES; + + return path; +} static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) { @@ -137,65 +152,133 @@ pci_unmap_resource(void *requested_addr, size_t size) requested_addr); } -/* Map pci device */ -int -pci_map_device(struct rte_pci_device *dev) +/* + * If vendor/device ID match, call the probe() function of the + * driver. + */ +static int +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev) { - int ret = -1; - - /* try mapping the NIC resources using VFIO if it exists */ - switch (dev->kdrv) { - case RTE_KDRV_VFIO: -#ifdef VFIO_PRESENT - if (pci_vfio_is_enabled()) - ret = pci_vfio_map_resource(dev); -#endif - break; - case RTE_KDRV_IGB_UIO: - case RTE_KDRV_UIO_GENERIC: - case RTE_KDRV_NIC_UIO: - /* map resources for devices that use uio */ - ret = pci_uio_map_resource(dev); - break; - default: - RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver," - " skipped\n"); - ret = 1; - break; - } + int ret; + const struct rte_pci_id *id_table; + + for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) { - return ret; + /* 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); + + 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; + } + + /* reference driver structure */ + dev->driver = dr; + + /* call the driver probe() function */ + ret = dr->probe(dr, dev); + if (ret) { + dev->driver = NULL; + if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) + rte_eal_pci_unmap_device(dev); + } + + return ret; + } + /* return positive value if driver doesn't support this device */ + return 1; } -#ifdef RTE_LIBRTE_EAL_HOTPLUG -/* Unmap pci device */ -void -pci_unmap_device(struct rte_pci_device *dev) +/* + * If vendor/device ID match, call the remove() function of the + * driver. + */ +static int +rte_eal_pci_detach_dev(struct rte_pci_driver *dr, + struct rte_pci_device *dev) { - if (dev == NULL) - return; + const struct rte_pci_id *id_table; + + if ((dr == NULL) || (dev == NULL)) + return -EINVAL; + + 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; + + struct rte_pci_addr *loc = &dev->addr; + + RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n", + loc->domain, loc->bus, loc->devid, + loc->function, dev->device.numa_node); + + RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", dev->id.vendor_id, + dev->id.device_id, dr->driver.name); + + if (dr->remove && (dr->remove(dev) < 0)) + return -1; /* negative value is an error */ + + /* clear driver structure */ + dev->driver = NULL; - /* try unmapping the NIC resources using VFIO if it exists */ - switch (dev->kdrv) { - case RTE_KDRV_VFIO: - RTE_LOG(ERR, EAL, "Hotplug doesn't support vfio yet\n"); - break; - case RTE_KDRV_IGB_UIO: - case RTE_KDRV_UIO_GENERIC: - case RTE_KDRV_NIC_UIO: - /* unmap resources for devices that use uio */ - pci_uio_unmap_resource(dev); - break; - default: - RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver," - " skipped\n"); - break; + if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) + /* unmap resources for devices that use igb_uio */ + rte_eal_pci_unmap_device(dev); + + return 0; } + + /* return positive value if driver doesn't support this device */ + return 1; } -#endif /* RTE_LIBRTE_EAL_HOTPLUG */ /* - * If vendor/device ID match, call the devinit() function of all + * If vendor/device ID match, call the probe() function of all * registered driver for the given device. Return -1 if initialization * failed, return 1 if no driver is found for this device. */ @@ -208,27 +291,30 @@ pci_probe_all_drivers(struct rte_pci_device *dev) if (dev == NULL) return -1; + /* Check if a driver is already loaded */ + 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 not found */ + /* positive value means driver doesn't support it */ continue; return 0; } return 1; } -#ifdef RTE_LIBRTE_EAL_HOTPLUG /* - * If vendor/device ID match, call the devuninit() function of all + * If vendor/device ID match, call the remove() function of all * registered driver for the given device. Return -1 if initialization * failed, return 1 if no driver is found for this device. */ static int -pci_close_all_drivers(struct rte_pci_device *dev) +pci_detach_all_drivers(struct rte_pci_device *dev) { struct rte_pci_driver *dr = NULL; int rc = 0; @@ -237,12 +323,12 @@ pci_close_all_drivers(struct rte_pci_device *dev) return -1; TAILQ_FOREACH(dr, &pci_driver_list, next) { - rc = rte_eal_pci_close_one_driver(dr, dev); + rc = rte_eal_pci_detach_dev(dr, dev); if (rc < 0) /* negative value is an error */ return -1; if (rc > 0) - /* positive value means driver not found */ + /* positive value means driver doesn't support it */ continue; return 0; } @@ -262,30 +348,35 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr) if (addr == NULL) 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) { if (rte_eal_compare_pci_addr(&dev->addr, addr)) continue; ret = pci_probe_all_drivers(dev); - if (ret < 0) + if (ret) goto err_return; return 0; } return -1; err_return: - RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT - " cannot be used\n", dev->addr.domain, dev->addr.bus, - dev->addr.devid, dev->addr.function); + RTE_LOG(WARNING, EAL, + "Requested device " PCI_PRI_FMT " cannot be used\n", + addr->domain, addr->bus, addr->devid, addr->function); return -1; } /* - * Find the pci device specified by pci address, then invoke close function of - * the driver of the devive. + * Detach device specified by its pci address. */ int -rte_eal_pci_close_one(const struct rte_pci_addr *addr) +rte_eal_pci_detach(const struct rte_pci_addr *addr) { struct rte_pci_device *dev = NULL; int ret = 0; @@ -297,11 +388,12 @@ rte_eal_pci_close_one(const struct rte_pci_addr *addr) if (rte_eal_compare_pci_addr(&dev->addr, addr)) continue; - ret = pci_close_all_drivers(dev); + ret = pci_detach_all_drivers(dev); if (ret < 0) goto err_return; TAILQ_REMOVE(&pci_device_list, dev, next); + free(dev); return 0; } return -1; @@ -312,10 +404,9 @@ err_return: dev->addr.devid, dev->addr.function); return -1; } -#endif /* RTE_LIBRTE_EAL_HOTPLUG */ /* - * Scan the content of the PCI bus, and call the devinit() function for + * 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. */ @@ -335,7 +426,7 @@ rte_eal_pci_probe(void) /* set devargs in PCI structure */ devargs = pci_devargs_lookup(dev); if (devargs != NULL) - dev->devargs = devargs; + dev->device.devargs = devargs; /* probe all or only whitelisted devices */ if (probe_all) @@ -388,11 +479,13 @@ void rte_eal_pci_register(struct rte_pci_driver *driver) { TAILQ_INSERT_TAIL(&pci_driver_list, driver, next); + rte_eal_driver_register(&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); }