hotplug which deals with resources should come from the layer that already handles them, i.e. eal.
Signed-off-by: David Marchand <david.marchand at 6wind.com> --- lib/librte_eal/bsdapp/eal/rte_eal_version.map | 8 + lib/librte_eal/common/eal_common_dev.c | 39 ++++ lib/librte_eal/common/eal_common_pci.c | 11 +- lib/librte_eal/common/include/rte_dev.h | 25 +++ lib/librte_eal/linuxapp/eal/rte_eal_version.map | 8 + lib/librte_ether/rte_ethdev.c | 258 ++++-------------------- 6 files changed, 125 insertions(+), 224 deletions(-) diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index 9d7adf1..9aad048 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -135,3 +135,11 @@ DPDK_2.2 { rte_xen_dom0_supported; } DPDK_2.1; + +DPDK_2.3 { + global: + + rte_eal_dev_attach; + rte_eal_dev_detach; + +} DPDK_2.2; diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 5137172..ec04b3a 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -155,3 +155,42 @@ rte_eal_vdev_uninit(const char *name) RTE_LOG(ERR, EAL, "no driver found for %s\n", name); return -EINVAL; } + +int rte_eal_dev_attach(const char *name, const char *devargs) +{ + struct rte_pci_addr addr; + int ret = -1; + + if (eal_parse_pci_DomBDF(name, &addr) == 0) { + if (rte_eal_pci_probe_one(&addr) < 0) + goto err; + + } else { + if (rte_eal_vdev_init(name, devargs)) + goto err; + } + + return 0; + +err: + RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n"); + return ret; +} + +int rte_eal_dev_detach(const char *name) +{ + struct rte_pci_addr addr; + + if (eal_parse_pci_DomBDF(name, &addr) == 0) { + if (rte_eal_pci_detach(&addr) < 0) + goto err; + } else { + if (rte_eal_vdev_uninit(name)) + goto err; + } + return 0; + +err: + RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n"); + return -1; +} diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index 1e12776..d9aa66b 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -332,6 +332,11 @@ 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_refresh_device(addr) < 0) + goto err_return; + TAILQ_FOREACH(dev, &pci_device_list, next) { if (rte_eal_compare_pci_addr(&dev->addr, addr)) continue; @@ -344,9 +349,9 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr) 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; } diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index df69e28..6f026ff 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -182,6 +182,31 @@ int rte_eal_vdev_init(const char *name, const char *args); */ int rte_eal_vdev_uninit(const char *name); +/** + * Attach a resource to a registered driver. + * + * @param name + * The resource name, that refers to a pci resource or some private + * way of designating a resource for vdev drivers. Based on this + * resource name, eal will identify a driver capable of handling + * this resource and pass this resource to the driver probing + * function. + * @param devargs + * Device arguments to be passed to the driver. + * @return + * 0 on success, negative on error. + */ +int rte_eal_dev_attach(const char *name, const char *devargs); + +/** + * Detach a resource from its driver. + * + * @param name + * Same description as for rte_eal_dev_attach(). + * Here, eal will call the driver detaching function. + */ +int rte_eal_dev_detach(const char *name); + #define PMD_REGISTER_DRIVER(d)\ void devinitfn_ ##d(void);\ void __attribute__((constructor, used)) devinitfn_ ##d(void)\ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index cbe175f..ba0ff56 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -138,3 +138,11 @@ DPDK_2.2 { rte_xen_dom0_supported; } DPDK_2.1; + +DPDK_2.3 { + global: + + rte_eal_dev_attach; + rte_eal_dev_detach; + +} DPDK_2.2; diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 5ba7479..5a5d419 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -72,6 +72,7 @@ static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data"; struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; static struct rte_eth_dev_data *rte_eth_dev_data; +static uint8_t eth_dev_last_created_port; static uint8_t nb_ports; /* spinlock for eth device callbacks */ @@ -210,6 +211,7 @@ rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type) eth_dev->data->port_id = port_id; eth_dev->attached = DEV_ATTACHED; eth_dev->dev_type = type; + eth_dev_last_created_port = port_id; nb_ports++; return eth_dev; } @@ -364,100 +366,6 @@ rte_eth_dev_count(void) return nb_ports; } -static enum rte_eth_dev_type -rte_eth_dev_get_device_type(uint8_t port_id) -{ - if (!rte_eth_dev_is_valid_port(port_id)) - return RTE_ETH_DEV_UNKNOWN; - return rte_eth_devices[port_id].dev_type; -} - -static int -rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) -{ - RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); - - if (addr == NULL) { - RTE_PMD_DEBUG_TRACE("Null pointer is specified\n"); - return -EINVAL; - } - - *addr = rte_eth_devices[port_id].pci_dev->addr; - return 0; -} - -static int -rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) -{ - char *tmp; - - RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); - - if (name == NULL) { - RTE_PMD_DEBUG_TRACE("Null pointer is specified\n"); - return -EINVAL; - } - - /* shouldn't check 'rte_eth_devices[i].data', - * because it might be overwritten by VDEV PMD */ - tmp = rte_eth_dev_data[port_id].name; - strcpy(name, tmp); - return 0; -} - -static int -rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id) -{ - int i; - - if (name == NULL) { - RTE_PMD_DEBUG_TRACE("Null pointer is specified\n"); - return -EINVAL; - } - - *port_id = RTE_MAX_ETHPORTS; - - for (i = 0; i < RTE_MAX_ETHPORTS; i++) { - - if (!strncmp(name, - rte_eth_dev_data[i].name, strlen(name))) { - - *port_id = i; - - return 0; - } - } - return -ENODEV; -} - -static int -rte_eth_dev_get_port_by_addr(const struct rte_pci_addr *addr, uint8_t *port_id) -{ - int i; - struct rte_pci_device *pci_dev = NULL; - - if (addr == NULL) { - RTE_PMD_DEBUG_TRACE("Null pointer is specified\n"); - return -EINVAL; - } - - *port_id = RTE_MAX_ETHPORTS; - - for (i = 0; i < RTE_MAX_ETHPORTS; i++) { - - pci_dev = rte_eth_devices[i].pci_dev; - - if (pci_dev && - !rte_eal_compare_pci_addr(&pci_dev->addr, addr)) { - - *port_id = i; - - return 0; - } - } - return -ENODEV; -} - static int rte_eth_dev_is_detachable(uint8_t port_id) { @@ -482,127 +390,50 @@ rte_eth_dev_is_detachable(uint8_t port_id) return !(dev_flags & RTE_ETH_DEV_DETACHABLE); } -/* attach the new physical device, then store port_id of the device */ -static int -rte_eth_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) -{ - /* re-construct pci_device_list */ - if (rte_eal_pci_scan()) - goto err; - /* Invoke probe func of the driver can handle the new device. */ - if (rte_eal_pci_probe_one(addr)) - goto err; - - if (rte_eth_dev_get_port_by_addr(addr, port_id)) - goto err; - - return 0; -err: - return -1; -} - -/* detach the new physical device, then store pci_addr of the device */ -static int -rte_eth_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) -{ - struct rte_pci_addr freed_addr; - struct rte_pci_addr vp; - - /* get pci address by port id */ - if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr)) - goto err; - - /* Zeroed pci addr means the port comes from virtual device */ - vp.domain = vp.bus = vp.devid = vp.function = 0; - if (rte_eal_compare_pci_addr(&vp, &freed_addr) == 0) - goto err; - - /* invoke devuninit func of the pci driver, - * also remove the device from pci_device_list */ - if (rte_eal_pci_detach(&freed_addr)) - goto err; - - *addr = freed_addr; - return 0; -err: - return -1; -} - -/* attach the new virtual device, then store port_id of the device */ -static int -rte_eth_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) -{ - char *name = NULL, *args = NULL; - int ret = -1; - - /* parse vdevargs, then retrieve device name and args */ - if (rte_eal_parse_devargs_str(vdevargs, &name, &args)) - goto end; - - /* walk around dev_driver_list to find the driver of the device, - * then invoke probe function of the driver. - * rte_eal_vdev_init() updates port_id allocated after - * initialization. - */ - if (rte_eal_vdev_init(name, args)) - goto end; - - if (rte_eth_dev_get_port_by_name(name, port_id)) - goto end; - - ret = 0; -end: - free(name); - free(args); - - return ret; -} - -/* detach the new virtual device, then store the name of the device */ -static int -rte_eth_dev_detach_vdev(uint8_t port_id, char *vdevname) -{ - char name[RTE_ETH_NAME_MAX_LEN]; - - /* get device name by port id */ - if (rte_eth_dev_get_name_by_port(port_id, name)) - goto err; - /* walk around dev_driver_list to find the driver of the device, - * then invoke uninit function of the driver */ - if (rte_eal_vdev_uninit(name)) - goto err; - - strncpy(vdevname, name, sizeof(name)); - return 0; -err: - return -1; -} - /* attach the new device, then store port_id of the device */ int rte_eth_dev_attach(const char *devargs, uint8_t *port_id) { - struct rte_pci_addr addr; int ret = -1; + int current = eth_dev_last_created_port; + char *name = NULL, *args; if ((devargs == NULL) || (port_id == NULL)) { ret = -EINVAL; goto err; } - if (eal_parse_pci_DomBDF(devargs, &addr) == 0) { - ret = rte_eth_dev_attach_pdev(&addr, port_id); - if (ret < 0) - goto err; - } else { - ret = rte_eth_dev_attach_vdev(devargs, port_id); - if (ret < 0) - goto err; + name = strdup(devargs); + if (!name) + goto err; + + args = strchr(name, ','); + if (args) { + args[0] = '\0'; + args++; } + ret = rte_eal_dev_attach(name, args); + if (ret < 0) + goto err; + + /* no point looking at eth_dev_last_created_port if no port exists */ + if (!nb_ports) { + ret = -1; + goto err; + } + /* if nothing happened, there is a bug here, since some driver told us + * it did attach a device, but did not create a port */ + if (current == eth_dev_last_created_port) { + ret = -1; + goto err; + } + *port_id = eth_dev_last_created_port; + + free(name); return 0; err: - RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n"); + free(name); return ret; } @@ -610,7 +441,6 @@ err: int rte_eth_dev_detach(uint8_t port_id, char *name) { - struct rte_pci_addr addr; int ret = -1; if (name == NULL) { @@ -618,33 +448,19 @@ rte_eth_dev_detach(uint8_t port_id, char *name) goto err; } - /* check whether the driver supports detach feature, or not */ + /* FIXME: move this to eal, once device flags are relocated there */ if (rte_eth_dev_is_detachable(port_id)) goto err; - if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PCI) { - ret = rte_eth_dev_get_addr_by_port(port_id, &addr); - if (ret < 0) - goto err; - - ret = rte_eth_dev_detach_pdev(port_id, &addr); - if (ret < 0) - goto err; - - snprintf(name, RTE_ETH_NAME_MAX_LEN, - "%04x:%02x:%02x.%d", - addr.domain, addr.bus, - addr.devid, addr.function); - } else { - ret = rte_eth_dev_detach_vdev(port_id, name); - if (ret < 0) - goto err; - } + snprintf(name, sizeof(rte_eth_devices[port_id].data->name), + "%s", rte_eth_devices[port_id].data->name); + ret = rte_eal_dev_detach(name); + if (ret < 0) + goto err; return 0; err: - RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n"); return ret; } -- 1.9.1