On 2/2/2015 1:43 PM, Qiu, Michael wrote: > On 2/1/2015 12:02 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. >> >> v5: >> - Change function names like below. >> rte_eal_dev_find_and_invoke() to rte_eal_vdev_find_and_invoke(). >> rte_eal_dev_invoke() to rte_eal_vdev_invoke(). >> - Add code to handle a return value of rte_eal_devargs_remove(). >> - Fix pci address format in rte_eal_dev_detach(). >> v4: >> - Fix comment. >> - Add error checking. >> - Fix indent of 'if' statement. >> - Change function name. >>
[...] >> +/* 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_vdev_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"); Here "cannot detach the device\n" should be "cannot attach the device" I think. > Here also "Drver", > > > Thanks, > Michael >> + 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_vdev_find_and_invoke(name, RTE_EAL_INVOKE_TYPE_CLOSE)) >> + goto err; >> + /* remove the vdevname from devargs_list */ >> + if (rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, name)) >> + goto err; >> + >> + 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 1a362ab..8168a7a 100644 >> --- a/lib/librte_eal/common/eal_private.h >> +++ b/lib/librte_eal/common/eal_private.h >> @@ -163,6 +163,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 <sys/queue.h> >> +#include <rte_pci.h> >> >> /** 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 831422e..1f43688 100644 >> --- a/lib/librte_eal/linuxapp/eal/eal_pci.c >> +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c >> @@ -431,8 +431,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; >> @@ -764,7 +764,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; >> } >