X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_dev.c;h=fc8a4d2278ea2fac0e60da14cefba5ae49891bb3;hb=7b681637d26eb91c1253c03e3d0268a7e3e29b66;hp=a7a2c4bd24ecc03c8813349f7fd8b3e2e13d293f;hpb=3dcfe0390c90560bdd4295dcb009e217521ca4a3;p=dpdk.git diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index a7a2c4bd24..fc8a4d2278 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -37,58 +37,210 @@ #include #include +#include #include #include #include -#include #include #include "eal_private.h" +static int cmp_detached_dev_name(const struct rte_device *dev, + const void *_name) +{ + const char *name = _name; + + /* skip attached devices */ + if (dev->driver != NULL) + return 1; + + return strcmp(dev->name, name); +} + +static int cmp_dev_name(const struct rte_device *dev, const void *_name) +{ + const char *name = _name; + + return strcmp(dev->name, name); +} + int rte_eal_dev_attach(const char *name, const char *devargs) { - struct rte_pci_addr addr; + struct rte_bus *bus; + int ret; if (name == NULL || devargs == NULL) { RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n"); return -EINVAL; } - if (eal_parse_pci_DomBDF(name, &addr) == 0) { - if (rte_pci_probe_one(&addr) < 0) - goto err; + bus = rte_bus_find_by_device_name(name); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n", + name); + return -EINVAL; + } + if (strcmp(bus->name, "pci") == 0) + return rte_eal_hotplug_add("pci", name, devargs); + if (strcmp(bus->name, "vdev") != 0) { + RTE_LOG(ERR, EAL, "Device attach is only supported for PCI and vdev devices.\n"); + return -ENOTSUP; + } - } else { - if (rte_eal_vdev_init(name, devargs)) - goto err; + /* + * If we haven't found a bus device the user meant to "hotplug" a + * virtual device instead. + */ + ret = rte_vdev_init(name, devargs); + if (ret) + RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", + name); + return ret; +} + +int rte_eal_dev_detach(struct rte_device *dev) +{ + struct rte_bus *bus; + int ret; + + if (dev == NULL) { + RTE_LOG(ERR, EAL, "Invalid device provided.\n"); + return -EINVAL; } - return 0; + bus = rte_bus_find_by_device(dev); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n", + dev->name); + return -EINVAL; + } + + if (bus->unplug == NULL) { + RTE_LOG(ERR, EAL, "Bus function not supported\n"); + return -ENOTSUP; + } -err: - RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name); - return -EINVAL; + ret = bus->unplug(dev); + if (ret) + RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", + dev->name); + return ret; } -int rte_eal_dev_detach(const char *name) +static char * +full_dev_name(const char *bus, const char *dev, const char *args) { - struct rte_pci_addr addr; + char *name; + size_t len; + len = snprintf(NULL, 0, "%s:%s,%s", bus, dev, args); + name = calloc(1, len); if (name == NULL) { - RTE_LOG(ERR, EAL, "Invalid device provided.\n"); - return -EINVAL; + RTE_LOG(ERR, EAL, "Could not allocate full device name\n"); + return NULL; } + snprintf(name, len, "%s:%s,%s", bus, dev, args); + return name; +} - if (eal_parse_pci_DomBDF(name, &addr) == 0) { - if (rte_pci_detach(&addr) < 0) - goto err; - } else { - if (rte_eal_vdev_uninit(name)) - goto err; +int rte_eal_hotplug_add(const char *busname, const char *devname, + const char *devargs) +{ + struct rte_bus *bus; + struct rte_device *dev; + struct rte_devargs *da; + char *name; + int ret; + + bus = rte_bus_find_by_name(busname); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname); + return -ENOENT; + } + + if (bus->plug == NULL) { + RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n", + bus->name); + return -ENOTSUP; + } + + name = full_dev_name(busname, devname, devargs); + if (name == NULL) + return -ENOMEM; + + da = calloc(1, sizeof(*da)); + if (da == NULL) { + ret = -ENOMEM; + goto err_name; + } + + ret = rte_eal_devargs_parse(name, da); + if (ret) + goto err_devarg; + + ret = rte_eal_devargs_insert(da); + if (ret) + goto err_devarg; + + ret = bus->scan(); + if (ret) + goto err_devarg; + + dev = bus->find_device(NULL, cmp_detached_dev_name, devname); + if (dev == NULL) { + RTE_LOG(ERR, EAL, "Cannot find unplugged device (%s)\n", + devname); + ret = -ENODEV; + goto err_devarg; + } + + ret = bus->plug(dev); + if (ret) { + RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", + dev->name); + goto err_devarg; } + free(name); return 0; -err: - RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name); - return -EINVAL; +err_devarg: + if (rte_eal_devargs_remove(busname, devname)) { + free(da->args); + free(da); + } +err_name: + free(name); + return ret; +} + +int rte_eal_hotplug_remove(const char *busname, const char *devname) +{ + struct rte_bus *bus; + struct rte_device *dev; + int ret; + + bus = rte_bus_find_by_name(busname); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname); + return -ENOENT; + } + + if (bus->unplug == NULL) { + RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n", + bus->name); + return -ENOTSUP; + } + + dev = bus->find_device(NULL, cmp_dev_name, devname); + if (dev == NULL) { + RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname); + return -EINVAL; + } + + ret = bus->unplug(dev); + if (ret) + RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", + dev->name); + rte_eal_devargs_remove(busname, devname); + return ret; }