From 0fe11ec592b2bff1efa6653a9a5b073e4c7a73fd Mon Sep 17 00:00:00 2001 From: Tetsuya Mukawa Date: Thu, 26 Feb 2015 04:32:25 +0900 Subject: [PATCH] eal: add vdev init and uninit The patch adds following functions. - rte_eal_vdev_init(); - rte_eal_vdev_uninit(); - rte_eal_parse_devargs_str(). These functions are used for driver initialization and finalization. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 77 +++++++++++++++---- lib/librte_eal/common/eal_common_devargs.c | 54 ++++++++----- lib/librte_eal/common/include/rte_dev.h | 28 +++++++ lib/librte_eal/common/include/rte_devargs.h | 28 +++++++ .../linuxapp/eal/rte_eal_version.map | 3 + 5 files changed, 155 insertions(+), 35 deletions(-) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index eae5656527..92a5a94184 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -32,6 +32,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include "eal_private.h" @@ -61,6 +63,32 @@ rte_eal_driver_unregister(struct rte_driver *driver) TAILQ_REMOVE(&dev_driver_list, driver, next); } +int +rte_eal_vdev_init(const char *name, const char *args) +{ + struct rte_driver *driver; + + if (name == NULL) + return -EINVAL; + + TAILQ_FOREACH(driver, &dev_driver_list, next) { + if (driver->type != PMD_VDEV) + continue; + + /* + * search a driver prefix in virtual device name. + * For example, if the driver is pcap PMD, driver->name + * will be "eth_pcap", but "name" will be "eth_pcapN". + * So use strncmp to compare. + */ + if (!strncmp(driver->name, name, strlen(driver->name))) + return driver->init(name, args); + } + + RTE_LOG(ERR, EAL, "no driver found for %s\n", name); + return -EINVAL; +} + int rte_eal_dev_init(void) { @@ -79,22 +107,11 @@ rte_eal_dev_init(void) if (devargs->type != RTE_DEVTYPE_VIRTUAL) 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))) { - driver->init(devargs->virtual.drv_name, - devargs->args); - break; - } - } - - if (driver == NULL) { - rte_panic("no driver found for %s\n", - devargs->virtual.drv_name); + if (rte_eal_vdev_init(devargs->virtual.drv_name, + devargs->args)) { + RTE_LOG(ERR, EAL, "failed to initialize %s device\n", + devargs->virtual.drv_name); + return -1; } } @@ -107,3 +124,31 @@ rte_eal_dev_init(void) } return 0; } + +#ifdef RTE_LIBRTE_EAL_HOTPLUG +int +rte_eal_vdev_uninit(const char *name) +{ + struct rte_driver *driver; + + if (name == NULL) + return -EINVAL; + + TAILQ_FOREACH(driver, &dev_driver_list, next) { + if (driver->type != PMD_VDEV) + continue; + + /* + * search a driver prefix in virtual device name. + * For example, if the driver is pcap PMD, driver->name + * will be "eth_pcap", but "name" will be "eth_pcapN". + * So use strncmp to compare. + */ + if (!strncmp(driver->name, name, strlen(driver->name))) + return driver->uninit(name); + } + + RTE_LOG(ERR, EAL, "no driver found for %s\n", name); + return -EINVAL; +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG */ diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index eadd71975c..9b110f7cf1 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -44,13 +44,46 @@ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); +int +rte_eal_parse_devargs_str(const char *devargs_str, + char **drvname, char **drvargs) +{ + char *sep; + + if ((devargs_str) == NULL || (drvname) == NULL || (drvargs == NULL)) + return -1; + + *drvname = strdup(devargs_str); + if (drvname == NULL) { + RTE_LOG(ERR, EAL, + "cannot allocate temp memory for driver name\n"); + return -1; + } + + /* set the first ',' to '\0' to split name and arguments */ + sep = strchr(*drvname, ','); + if (sep != NULL) { + sep[0] = '\0'; + *drvargs = strdup(sep + 1); + } else { + *drvargs = strdup(""); + } + + if (*drvargs == NULL) { + RTE_LOG(ERR, EAL, + "cannot allocate temp memory for driver arguments\n"); + free(*drvname); + return -1; + } + return 0; +} + /* store a whitelist parameter for later parsing */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) { struct rte_devargs *devargs = NULL; char *buf = NULL; - char *sep; int ret; /* use malloc instead of rte_malloc as it's called early at init */ @@ -62,25 +95,8 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) memset(devargs, 0, sizeof(*devargs)); devargs->type = devtype; - buf = strdup(devargs_str); - if (buf == NULL) { - RTE_LOG(ERR, EAL, "cannot allocate temp memory for devargs\n"); - goto fail; - } - - /* set the first ',' to '\0' to split name and arguments */ - sep = strchr(buf, ','); - if (sep != NULL) { - sep[0] = '\0'; - devargs->args = strdup(sep + 1); - } else { - devargs->args = strdup(""); - } - - if (devargs->args == NULL) { - RTE_LOG(ERR, EAL, "cannot allocate for devargs args\n"); + if (rte_eal_parse_devargs_str(devargs_str, &buf, &devargs->args)) goto fail; - } switch (devargs->type) { case RTE_DEVTYPE_WHITELISTED_PCI: diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index f7e3a104a4..f601d21ea2 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -56,6 +56,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); + /** * Driver type enumeration */ @@ -72,6 +77,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. */ }; /** @@ -97,6 +103,28 @@ void rte_eal_driver_unregister(struct rte_driver *driver); */ int rte_eal_dev_init(void); +/** + * Initialize a driver specified by name. + * + * @param name + * The pointer to a driver name to be initialized. + * @param args + * The pointer to arguments used by driver initialization. + * @return + * 0 on success, negative on error + */ +int rte_eal_vdev_init(const char *name, const char *args); + +/** + * Uninitalize a driver specified by name. + * + * @param name + * The pointer to a driver name to be initialized. + * @return + * 0 on success, negative on error + */ +int rte_eal_vdev_uninit(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/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h index 68343339dc..039f728ecd 100644 --- a/lib/librte_eal/common/include/rte_devargs.h +++ b/lib/librte_eal/common/include/rte_devargs.h @@ -98,6 +98,34 @@ TAILQ_HEAD(rte_devargs_list, rte_devargs); /** Global list of user devices */ extern struct rte_devargs_list devargs_list; +/** + * Parse a devargs string. + * + * For PCI devices, the format of arguments string is "PCI_ADDR" or + * "PCI_ADDR,key=val,key2=val2,...". Examples: "08:00.1", "0000:5:00.0", + * "04:00.0,arg=val". + * + * For virtual devices, the format of arguments string is "DRIVER_NAME*" + * or "DRIVER_NAME*,key=val,key2=val2,...". Examples: "eth_ring", + * "eth_ring0", "eth_pmdAnything,arg=0:arg2=1". + * + * The function parses the arguments string to get driver name and driver + * arguments. + * + * @param devargs_str + * The arguments as given by the user. + * @param drvname + * The pointer to the string to store parsed driver name. + * @param drvargs + * The pointer to the string to store parsed driver arguments. + * + * @return + * - 0 on success + * - A negative value on error + */ +int rte_eal_parse_devargs_str(const char *devargs_str, + char **drvname, char **drvargs); + /** * Add a device to the user device list * diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 5478492460..214643d359 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -38,6 +38,7 @@ DPDK_2.0 { rte_eal_lcore_role; rte_eal_mp_remote_launch; rte_eal_mp_wait_lcore; + rte_eal_parse_devargs_str; rte_eal_pci_close_one; rte_eal_pci_dump; rte_eal_pci_probe; @@ -50,6 +51,8 @@ DPDK_2.0 { rte_eal_tailq_lookup_by_idx; rte_eal_tailq_reserve; rte_eal_tailq_reserve_by_idx; + rte_eal_vdev_init; + rte_eal_vdev_uninit; rte_eal_wait_lcore; rte_exit; rte_get_hpet_cycles; -- 2.20.1