X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_devargs.c;h=894749e4061f249f01ac562b823cbcc61135b319;hb=0436120e33e0e117ce294a024555f522a7e68fb3;hp=52f5cc76696ae4d68345a5b044c54b628bf5d81e;hpb=bf6dea0e04afc0d1f2c8056cd4d1aecab12502d1;p=dpdk.git diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index 52f5cc7669..894749e406 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -1,113 +1,202 @@ -/*- - * BSD LICENSE - * - * Copyright 2014 6WIND S.A. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of 6WIND S.A nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2014 6WIND S.A. */ /* This file manages the list of devices and their arguments, as given - * by the user at startup */ + * by the user at startup + * + * Code here should not call rte_log since the EAL environment + * may not be initialized. + */ +#include #include +#include -#include -#include +#include +#include #include +#include +#include #include "eal_private.h" +/** user device double-linked queue type definition */ +TAILQ_HEAD(rte_devargs_list, rte_devargs); + /** Global list of user devices */ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); -/* store a whitelist parameter for later parsing */ int -rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) +rte_eal_parse_devargs_str(const char *devargs_str, + char **drvname, char **drvargs) { - struct rte_devargs *devargs; - char buf[RTE_DEVARGS_LEN]; char *sep; - int ret; - ret = snprintf(buf, sizeof(buf), "%s", devargs_str); - if (ret < 0 || ret >= (int)sizeof(buf)) { - RTE_LOG(ERR, EAL, "user device args too large: <%s>\n", - devargs_str); + if ((devargs_str) == NULL || (drvname) == NULL || (drvargs == NULL)) return -1; - } - /* use malloc instead of rte_malloc as it's called early at init */ - devargs = malloc(sizeof(*devargs)); - if (devargs == NULL) { - RTE_LOG(ERR, EAL, "cannot allocate devargs\n"); + *drvname = strdup(devargs_str); + if (*drvname == NULL) return -1; - } - memset(devargs, 0, sizeof(*devargs)); - devargs->type = devtype; - /* set the first ';' to '\0' to split name and arguments */ - sep = strchr(buf, ';'); + /* set the first ',' to '\0' to split name and arguments */ + sep = strchr(*drvname, ','); if (sep != NULL) { sep[0] = '\0'; - snprintf(devargs->args, sizeof(devargs->args), "%s", sep + 1); + *drvargs = strdup(sep + 1); + } else { + *drvargs = strdup(""); } - switch (devargs->type) { - case RTE_DEVTYPE_WHITELISTED_PCI: - case RTE_DEVTYPE_BLACKLISTED_PCI: - /* try to parse pci identifier */ - if (eal_parse_pci_BDF(buf, &devargs->pci.addr) != 0 && - eal_parse_pci_DomBDF(buf, &devargs->pci.addr) != 0) { - RTE_LOG(ERR, EAL, - "invalid PCI identifier <%s>\n", buf); - free(devargs); - return -1; + if (*drvargs == NULL) { + free(*drvname); + *drvname = NULL; + return -1; + } + return 0; +} + +static int +bus_name_cmp(const struct rte_bus *bus, const void *name) +{ + return strncmp(bus->name, name, strlen(bus->name)); +} + +int __rte_experimental +rte_devargs_parse(struct rte_devargs *da, const char *format, ...) +{ + struct rte_bus *bus = NULL; + va_list ap; + va_start(ap, format); + char dev[vsnprintf(NULL, 0, format, ap) + 1]; + const char *devname; + const size_t maxlen = sizeof(da->name); + size_t i; + + va_end(ap); + if (da == NULL) + return -EINVAL; + + va_start(ap, format); + vsnprintf(dev, sizeof(dev), format, ap); + va_end(ap); + /* Retrieve eventual bus info */ + do { + devname = dev; + bus = rte_bus_find(bus, bus_name_cmp, dev); + if (bus == NULL) + break; + devname = dev + strlen(bus->name) + 1; + if (rte_bus_find_by_device_name(devname) == bus) + break; + } while (1); + /* Store device name */ + i = 0; + while (devname[i] != '\0' && devname[i] != ',') { + da->name[i] = devname[i]; + i++; + if (i == maxlen) { + RTE_LOG(WARNING, EAL, "Parsing \"%s\": device name should be shorter than %zu\n", + dev, maxlen); + da->name[i - 1] = '\0'; + return -EINVAL; } - break; - case RTE_DEVTYPE_VIRTUAL: - /* save driver name */ - ret = snprintf(devargs->virtual.drv_name, - sizeof(devargs->virtual.drv_name), "%s", buf); - if (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) { - RTE_LOG(ERR, EAL, - "driver name too large: <%s>\n", buf); - free(devargs); - return -1; + } + da->name[i] = '\0'; + if (bus == NULL) { + bus = rte_bus_find_by_device_name(da->name); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "failed to parse device \"%s\"\n", + da->name); + return -EFAULT; } - break; } + da->bus = bus; + /* Parse eventual device arguments */ + if (devname[i] == ',') + da->args = strdup(&devname[i + 1]); + else + da->args = strdup(""); + if (da->args == NULL) { + RTE_LOG(ERR, EAL, "not enough memory to parse arguments\n"); + return -ENOMEM; + } + return 0; +} + +int __rte_experimental +rte_devargs_insert(struct rte_devargs *da) +{ + int ret; + + ret = rte_devargs_remove(da->bus->name, da->name); + if (ret < 0) + return ret; + TAILQ_INSERT_TAIL(&devargs_list, da, next); + return 0; +} +/* store a whitelist parameter for later parsing */ +__rte_experimental +int +rte_devargs_add(enum rte_devtype devtype, const char *devargs_str) +{ + struct rte_devargs *devargs = NULL; + struct rte_bus *bus = NULL; + const char *dev = devargs_str; + + /* use calloc instead of rte_zmalloc as it's called early at init */ + devargs = calloc(1, sizeof(*devargs)); + if (devargs == NULL) + goto fail; + + if (rte_devargs_parse(devargs, "%s", dev)) + goto fail; + devargs->type = devtype; + bus = devargs->bus; + if (devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) + devargs->policy = RTE_DEV_BLACKLISTED; + if (bus->conf.scan_mode == RTE_BUS_SCAN_UNDEFINED) { + if (devargs->policy == RTE_DEV_WHITELISTED) + bus->conf.scan_mode = RTE_BUS_SCAN_WHITELIST; + else if (devargs->policy == RTE_DEV_BLACKLISTED) + bus->conf.scan_mode = RTE_BUS_SCAN_BLACKLIST; + } TAILQ_INSERT_TAIL(&devargs_list, devargs, next); return 0; + +fail: + if (devargs) { + free(devargs->args); + free(devargs); + } + + return -1; +} + +int __rte_experimental +rte_devargs_remove(const char *busname, const char *devname) +{ + struct rte_devargs *d; + void *tmp; + + TAILQ_FOREACH_SAFE(d, &devargs_list, next, tmp) { + if (strcmp(d->bus->name, busname) == 0 && + strcmp(d->name, devname) == 0) { + TAILQ_REMOVE(&devargs_list, d, next); + free(d->args); + free(d); + return 0; + } + } + return 1; } /* count the number of devices of a specified type */ +__rte_experimental unsigned int -rte_eal_devargs_type_count(enum rte_devtype devtype) +rte_devargs_type_count(enum rte_devtype devtype) { struct rte_devargs *devargs; unsigned int count = 0; @@ -121,32 +210,36 @@ rte_eal_devargs_type_count(enum rte_devtype devtype) } /* dump the user devices on the console */ +__rte_experimental void -rte_eal_devargs_dump(void) +rte_devargs_dump(FILE *f) { struct rte_devargs *devargs; - printf("User device white list:\n"); + fprintf(f, "User device list:\n"); TAILQ_FOREACH(devargs, &devargs_list, next) { - if (devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) - printf(" PCI whitelist " PCI_PRI_FMT " %s\n", - devargs->pci.addr.domain, - devargs->pci.addr.bus, - devargs->pci.addr.devid, - devargs->pci.addr.function, - devargs->args); - else if (devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) - printf(" PCI blacklist " PCI_PRI_FMT " %s\n", - devargs->pci.addr.domain, - devargs->pci.addr.bus, - devargs->pci.addr.devid, - devargs->pci.addr.function, - devargs->args); - else if (devargs->type == RTE_DEVTYPE_VIRTUAL) - printf(" VIRTUAL %s %s\n", - devargs->virtual.drv_name, - devargs->args); - else - printf(" UNKNOWN %s\n", devargs->args); + fprintf(f, " [%s]: %s %s\n", + (devargs->bus ? devargs->bus->name : "??"), + devargs->name, devargs->args); + } +} + +/* bus-aware rte_devargs iterator. */ +__rte_experimental +struct rte_devargs * +rte_devargs_next(const char *busname, const struct rte_devargs *start) +{ + struct rte_devargs *da; + + if (start != NULL) + da = TAILQ_NEXT(start, next); + else + da = TAILQ_FIRST(&devargs_list); + while (da != NULL) { + if (busname == NULL || + (strcmp(busname, da->bus->name) == 0)) + return da; + da = TAILQ_NEXT(da, next); } + return NULL; }