From patchwork Fri Jan 29 14:08:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 10266 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 490B4C712; Fri, 29 Jan 2016 15:08:56 +0100 (CET) Received: from mail-wm0-f50.google.com (mail-wm0-f50.google.com [74.125.82.50]) by dpdk.org (Postfix) with ESMTP id 9B9DFC6CE for ; Fri, 29 Jan 2016 15:08:51 +0100 (CET) Received: by mail-wm0-f50.google.com with SMTP id l66so56065950wml.0 for ; Fri, 29 Jan 2016 06:08:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uuWuawIr8Dxc/0u8+FLAfMerorHKn6ALUj103Yh7TAY=; b=TR4K/QqtW8LIs39mgBgeakClNi8CPQiukNGS1jwRnDxdx8G1y/bu4HlJH02jokrfj9 NXfls3P10vHOrtYsJ0KfDngNL5OONBH0ajAmAbLGkelf9Yfl2GD34QDNMKrWXzTvWLmO rVfcf3qEo6E+W2vqTuT7k4iplrc+4PcB3ZZhy/K8rBwRR5w8OQuzTh/jwP870AGiU8Un DJkpFjr+LmTZS4emzb/PYFKKL5y185Qalg2rXYT+4+SXrmrWhFwWVCkF8Xn4C9yda3gB zxz91PUVhmWP49CZRK5QHZQXzXAOMfYa4+0+IXYmyqbkkZ4J/TCNxHhFZOFLbGlLqwmJ qP7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uuWuawIr8Dxc/0u8+FLAfMerorHKn6ALUj103Yh7TAY=; b=kP8jTfM32nxOixREfnbiV9fjOtGF8qxXKQh8DmoJaOkFcvRYR7tH6bTFFkwQ5J00cD Py70mbed0H6MdkN3+VLwW3RQ6QZTE8eLL7EuybTy4uSHDK5PRpSFBWSBr4zu/VOqyr8x +tJZNorUJ9EMINuA9ZMd30q2nO4D+qexWRz8tb3D0pZbic6VhvXaZNpHICdAARfHPCRg rbazNGNtMkaLWploXHI9eEp4nN/CVcgHCn963o4wi4o6MyvR+ZXlUYpQJcIP0tMajyDS C6IIo1d0W3ZprL9IdUvH6hIhbIPfbMgoolS+ysnWMgCmS6ZjV5mfSE6ls+0nOisg4oBw scFQ== X-Gm-Message-State: AG10YOTWLQMmo7O88DquVw3VmQ7pHNta2mm96fnXzk/XIO2EO9/Pa0r1J/0JPSVF3GZHLVXq X-Received: by 10.28.223.134 with SMTP id w128mr8837677wmg.69.1454076531469; Fri, 29 Jan 2016 06:08:51 -0800 (PST) Received: from gloops.dev.6wind.com (144.77.126.78.rev.sfr.net. [78.126.77.144]) by smtp.gmail.com with ESMTPSA id 67sm7669944wmp.20.2016.01.29.06.08.50 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 29 Jan 2016 06:08:50 -0800 (PST) From: David Marchand To: dev@dpdk.org Date: Fri, 29 Jan 2016 15:08:36 +0100 Message-Id: <1454076516-21591-10-git-send-email-david.marchand@6wind.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1454076516-21591-1-git-send-email-david.marchand@6wind.com> References: <1454076516-21591-1-git-send-email-david.marchand@6wind.com> Cc: viktorin@rehivetech.com Subject: [dpdk-dev] [PATCH 9/9] eal: relocate hotplug code from ethdev X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" hotplug which deals with resources should come from the layer that already handles them, i.e. eal. Signed-off-by: David Marchand --- 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; }