From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com [209.85.220.47]) by dpdk.org (Postfix) with ESMTP id 99A985A1F for ; Wed, 21 Jan 2015 07:34:50 +0100 (CET) Received: by mail-pa0-f47.google.com with SMTP id lj1so6577527pab.6 for ; Tue, 20 Jan 2015 22:34:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type :content-transfer-encoding; bh=6nEW09igIhr91MuurKqVkaNi8b1Kqpyn/mtpBcQ0BNQ=; b=Krle1VnOrDanX7QEjqsmStUtMn7MCACsYPSQe9fle3z8WE4ek44lc1CPGi3Pj9cPtY WoK+DuBNob0u5vTotBf+1wsSWraoApFLbXRU6VykeZJJNYVCVRfZIBRX3UiF1T6gUrEi EXh2ucVZQN7OSRS9geV2JVrd3r6M41gZ3NS4/uVANmxA1+giZ16trux9sRfS14hYvT/I Hj0sPSj81bu+tq5cZxcZgyBp5mN1Gi1m9UKMGZvAeTcwGRFGuBDUpzVT64f7tIZjtL+7 XSONccgLxChCXC35/9M7KybmSf211tZWreGfoMEE4Z4R4rw/OKocjmf6sVXsolUCpnsq ai9A== X-Gm-Message-State: ALoCoQklGU8Nw/fkqIk9MBlX2g/+LrC1vtotaoNnUM7ZbAwzSyOTyEp16gT0B7AncG1Rh48wkHgc X-Received: by 10.68.208.65 with SMTP id mc1mr59565409pbc.111.1421822089927; Tue, 20 Jan 2015 22:34:49 -0800 (PST) Received: from [10.16.129.101] (napt.igel.co.jp. [219.106.231.132]) by mx.google.com with ESMTPSA id ut7sm4824467pbc.8.2015.01.20.22.34.48 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Jan 2015 22:34:49 -0800 (PST) Message-ID: <54BF4887.6090906@igel.co.jp> Date: Wed, 21 Jan 2015 15:34:47 +0900 From: Tetsuya Mukawa User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: "Qiu, Michael" References: <1418106629-22227-2-git-send-email-mukawa@igel.co.j> <1421664027-17971-1-git-send-email-mukawa@igel.co.jp> <1421664027-17971-11-git-send-email-mukawa@igel.co.jp> <533710CFB86FA344BFBF2D6802E60286CB7FB0@SHSMSX101.ccr.corp.intel.com> In-Reply-To: <533710CFB86FA344BFBF2D6802E60286CB7FB0@SHSMSX101.ccr.corp.intel.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Cc: "dev@dpdk.org" Subject: Re: [dpdk-dev] [PATCH v4 10/11] eal/pci: Add rte_eal_dev_attach/detach() functions 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: , X-List-Received-Date: Wed, 21 Jan 2015 06:34:51 -0000 Hi Michael, On 2015/01/21 12:49, Qiu, Michael wrote: > On 1/19/2015 6:43 PM, Tetsuya Mukawa wrote: >> These functions are used for attaching or detaching a port. >> When rte_eal_dev_attach() is called, the function tries to realize the >> device name as pci address. If this is done successfully, >> rte_eal_dev_attach() will attach physical device port. If not, attaches >> virtual devive port. >> When rte_eal_dev_detach() is called, the function gets the device type >> of this port to know whether the port is came from physical or virtual. >> And then specific detaching function will be called. >> >> v4: >> - Fix comment. >> - Add error checking. >> - Fix indent of 'if' statement. >> - Change function name. >> >> Signed-off-by: Tetsuya Mukawa >> --- >> lib/librte_eal/common/eal_common_dev.c | 273 ++++++++++++++++++++++++++++++++ >> lib/librte_eal/common/eal_private.h | 11 ++ >> lib/librte_eal/common/include/rte_dev.h | 33 ++++ >> lib/librte_eal/linuxapp/eal/Makefile | 1 + >> lib/librte_eal/linuxapp/eal/eal_pci.c | 6 +- >> 5 files changed, 321 insertions(+), 3 deletions(-) >> >> diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c >> index eae5656..828bd70 100644 >> --- a/lib/librte_eal/common/eal_common_dev.c >> +++ b/lib/librte_eal/common/eal_common_dev.c >> @@ -32,10 +32,13 @@ >> * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >> */ >> >> +#include >> +#include >> #include >> #include >> #include >> >> +#include >> #include >> #include >> #include >> @@ -107,3 +110,273 @@ rte_eal_dev_init(void) >> } >> return 0; >> } >> + >> +/* So far, DPDK hotplug function only supports linux */ >> +#ifdef ENABLE_HOTPLUG >> +static void >> +rte_eal_dev_invoke(struct rte_driver *driver, >> + struct rte_devargs *devargs, enum rte_eal_invoke_type type) >> +{ >> + if ((driver == NULL) || (devargs == NULL)) >> + return; >> + >> + switch (type) { >> + case RTE_EAL_INVOKE_TYPE_PROBE: >> + driver->init(devargs->virtual.drv_name, devargs->args); >> + break; >> + case RTE_EAL_INVOKE_TYPE_CLOSE: >> + driver->uninit(devargs->virtual.drv_name, devargs->args); >> + break; >> + default: >> + break; >> + } >> +} >> + >> +static int >> +rte_eal_dev_find_and_invoke(const char *name, int type) > This function is totally for vdev, so I would like it shows in name, > like *rte_eal_vdev_find_and_invoke* Sure, I will change like above. I appreciate your suggestion. Thanks, Tetsuya >> +{ >> + struct rte_devargs *devargs; >> + struct rte_driver *driver; >> + >> + if (name == NULL) >> + return -EINVAL; >> + >> + /* call the init function for each virtual device */ >> + TAILQ_FOREACH(devargs, &devargs_list, next) { >> + >> + if (devargs->type != RTE_DEVTYPE_VIRTUAL) >> + continue; >> + >> + if (strncmp(name, devargs->virtual.drv_name, strlen(name))) >> + continue; >> + >> + TAILQ_FOREACH(driver, &dev_driver_list, next) { >> + if (driver->type != PMD_VDEV) >> + continue; >> + >> + /* search a driver prefix in virtual device name */ >> + if (!strncmp(driver->name, devargs->virtual.drv_name, >> + strlen(driver->name))) { >> + rte_eal_dev_invoke(driver, devargs, type); >> + break; >> + } >> + } >> + >> + if (driver == NULL) { >> + RTE_LOG(WARNING, EAL, "no driver found for %s\n", >> + devargs->virtual.drv_name); >> + } >> + return 0; >> + } >> + return 1; >> +} >> + >> +/* attach the new physical device, then store port_id of the device */ >> +static int >> +rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) >> +{ >> + uint8_t new_port_id; >> + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; >> + >> + if ((addr == NULL) || (port_id == NULL)) >> + goto err; >> + >> + /* save current port status */ >> + rte_eth_dev_save(devs); >> + /* 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; >> + /* get port_id enabled by above procedures */ >> + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) >> + goto err; >> + >> + *port_id = new_port_id; >> + return 0; >> +err: >> + RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n"); >> + return -1; >> +} >> + >> +/* detach the new physical device, then store pci_addr of the device */ >> +static int >> +rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) >> +{ >> + struct rte_pci_addr freed_addr; >> + struct rte_pci_addr vp; >> + >> + if (addr == NULL) >> + goto err; >> + >> + /* check whether the driver supports detach feature, or not */ >> + if (rte_eth_dev_check_detachable(port_id)) >> + goto err; >> + >> + /* get pci address by port id */ >> + if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr)) >> + goto err; >> + >> + /* Zerod pci addr means the port comes from virtual device */ >> + vp.domain = vp.bus = vp.devid = vp.function = 0; >> + if (eal_compare_pci_addr(&vp, &freed_addr) == 0) >> + goto err; >> + >> + /* invoke close func of the driver, >> + * also remove the device from pci_device_list */ >> + if (rte_eal_pci_close_one(&freed_addr)) >> + goto err; >> + >> + *addr = freed_addr; >> + return 0; >> +err: >> + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); >> + return -1; >> +} >> + >> +static void >> +get_vdev_name(char *vdevargs) >> +{ >> + char *sep; >> + >> + if (vdevargs == NULL) >> + return; >> + >> + /* set the first ',' to '\0' to split name and arguments */ >> + sep = strchr(vdevargs, ','); >> + if (sep != NULL) >> + sep[0] = '\0'; >> +} >> + >> +/* attach the new virtual device, then store port_id of the device */ >> +static int >> +rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) >> +{ >> + char *args; >> + uint8_t new_port_id; >> + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; >> + >> + if ((vdevargs == NULL) || (port_id == NULL)) >> + goto err0; >> + >> + args = strdup(vdevargs); >> + if (args == NULL) >> + goto err0; >> + >> + /* save current port status */ >> + rte_eth_dev_save(devs); >> + /* add the vdevargs to devargs_list */ >> + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, args)) >> + goto err1; >> + /* parse vdevargs, then retrieve device name */ >> + get_vdev_name(args); >> + /* walk around dev_driver_list to find the driver of the device, >> + * then invoke probe function o the driver */ >> + if (rte_eal_dev_find_and_invoke(args, RTE_EAL_INVOKE_TYPE_PROBE)) >> + goto err2; >> + /* get port_id enabled by above procedures */ >> + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) >> + goto err2; >> + >> + free(args); >> + *port_id = new_port_id; >> + return 0; >> +err2: >> + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, args); >> +err1: >> + free(args); >> +err0: >> + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); >> + return -1; >> +} >> + >> +/* detach the new virtual device, then store the name of the device */ >> +static int >> +rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname) >> +{ >> + char name[RTE_ETH_NAME_MAX_LEN]; >> + >> + if (vdevname == NULL) >> + goto err; >> + >> + /* check whether the driver supports detach feature, or not */ >> + if (rte_eth_dev_check_detachable(port_id)) >> + goto err; >> + >> + /* 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 close function o the driver */ >> + if (rte_eal_dev_find_and_invoke(name, RTE_EAL_INVOKE_TYPE_CLOSE)) >> + goto err; >> + /* remove the vdevname from devargs_list */ >> + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, name); >> + >> + strncpy(vdevname, name, sizeof(name)); >> + return 0; >> +err: >> + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); >> + return -1; >> +} >> + >> +/* attach the new device, then store port_id of the device */ >> +int >> +rte_eal_dev_attach(const char *devargs, uint8_t *port_id) >> +{ >> + struct rte_pci_addr addr; >> + >> + if ((devargs == NULL) || (port_id == NULL)) >> + return -EINVAL; >> + >> + if (eal_parse_pci_DomBDF(devargs, &addr) == 0) >> + return rte_eal_dev_attach_pdev(&addr, port_id); >> + else >> + return rte_eal_dev_attach_vdev(devargs, port_id); >> +} >> + >> +/* detach the device, then store the name of the device */ >> +int >> +rte_eal_dev_detach(uint8_t port_id, char *name) >> +{ >> + struct rte_pci_addr addr; >> + int ret; >> + >> + if (name == NULL) >> + return -EINVAL; >> + >> + if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PHYSICAL) { >> + ret = rte_eth_dev_get_addr_by_port(port_id, &addr); >> + if (ret < 0) >> + return ret; >> + >> + ret = rte_eal_dev_detach_pdev(port_id, &addr); >> + if (ret == 0) >> + snprintf(name, RTE_ETH_NAME_MAX_LEN, >> + "%04x.%02x.%02x.%d", >> + addr.domain, addr.bus, >> + addr.devid, addr.function); >> + >> + return ret; >> + } else >> + return rte_eal_dev_detach_vdev(port_id, name); >> +} >> +#else /* ENABLE_HOTPLUG */ >> +int >> +rte_eal_dev_attach(const char *devargs __rte_unused, >> + uint8_t *port_id __rte_unused) >> +{ >> + RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n"); >> + return -1; >> +} >> + >> +/* detach the device, then store the name of the device */ >> +int >> +rte_eal_dev_detach(uint8_t port_id __rte_unused, >> + char *name __rte_unused) >> +{ >> + RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n"); >> + return -1; >> +} >> +#endif /* ENABLE_HOTPLUG */ >> diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h >> index a97c5d8..453a1eb 100644 >> --- a/lib/librte_eal/common/eal_private.h >> +++ b/lib/librte_eal/common/eal_private.h >> @@ -164,6 +164,17 @@ enum rte_eal_invoke_type { >> }; >> >> /** >> + * Scan the content of the PCI bus, and the devices in the devices >> + * list >> + * >> + * This function is private to EAL. >> + * >> + * @return >> + * 0 on success, negative on error >> + */ >> +int rte_eal_pci_scan(void); >> + >> +/** >> * Mmap memory for single PCI device >> * >> * This function is private to EAL. >> diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h >> index f7e3a10..e63dd1c 100644 >> --- a/lib/librte_eal/common/include/rte_dev.h >> +++ b/lib/librte_eal/common/include/rte_dev.h >> @@ -47,6 +47,7 @@ extern "C" { >> #endif >> >> #include >> +#include >> >> /** Double linked list of device drivers. */ >> TAILQ_HEAD(rte_driver_list, rte_driver); >> @@ -57,6 +58,11 @@ TAILQ_HEAD(rte_driver_list, rte_driver); >> typedef int (rte_dev_init_t)(const char *name, const char *args); >> >> /** >> + * Uninitilization function called for each device driver once. >> + */ >> +typedef int (rte_dev_uninit_t)(const char *name, const char *args); >> + >> +/** >> * Driver type enumeration >> */ >> enum pmd_type { >> @@ -72,6 +78,7 @@ struct rte_driver { >> enum pmd_type type; /**< PMD Driver type */ >> const char *name; /**< Driver name. */ >> rte_dev_init_t *init; /**< Device init. function. */ >> + rte_dev_uninit_t *uninit; /**< Device uninit. function. */ >> }; >> >> /** >> @@ -93,6 +100,32 @@ void rte_eal_driver_register(struct rte_driver *driver); >> void rte_eal_driver_unregister(struct rte_driver *driver); >> >> /** >> + * Attach a new device. >> + * >> + * @param devargs >> + * A pointer to a strings array describing the new device >> + * to be attached. The strings should be a pci address like >> + * '0000:01:00.0' or virtual device name like 'eth_pcap0'. >> + * @param port_id >> + * A pointer to a port identifier actually attached. >> + * @return >> + * 0 on success and port_id is filled, negative on error >> + */ >> +int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); >> + >> +/** >> + * Detach a device. >> + * >> + * @param port_id >> + * The port identifier of the device to detach. >> + * @param addr >> + * A pointer to a device name actually detached. >> + * @return >> + * 0 on success and devname is filled, negative on error >> + */ >> +int rte_eal_dev_detach(uint8_t port_id, char *devname); >> + >> +/** >> * Initalize all the registered drivers in this process >> */ >> int rte_eal_dev_init(void); >> diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile >> index 72ecf3a..0ec83b5 100644 >> --- a/lib/librte_eal/linuxapp/eal/Makefile >> +++ b/lib/librte_eal/linuxapp/eal/Makefile >> @@ -41,6 +41,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include >> CFLAGS += -I$(RTE_SDK)/lib/librte_ring >> CFLAGS += -I$(RTE_SDK)/lib/librte_mempool >> CFLAGS += -I$(RTE_SDK)/lib/librte_malloc >> +CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf >> CFLAGS += -I$(RTE_SDK)/lib/librte_ether >> CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem >> CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_ring >> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c >> index a23cc59..8e7e650 100644 >> --- a/lib/librte_eal/linuxapp/eal/eal_pci.c >> +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c >> @@ -378,8 +378,8 @@ error: >> * Scan the content of the PCI bus, and the devices in the devices >> * list >> */ >> -static int >> -pci_scan(void) >> +int >> +rte_eal_pci_scan(void) >> { >> struct dirent *e; >> DIR *dir; >> @@ -701,7 +701,7 @@ rte_eal_pci_init(void) >> if (internal_config.no_pci) >> return 0; >> >> - if (pci_scan() < 0) { >> + if (rte_eal_pci_scan() < 0) { >> RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__); >> return -1; >> }