From patchwork Tue Jun 26 16:56:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ga=C3=ABtan_Rivet?= X-Patchwork-Id: 41598 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E63B31BE4B; Tue, 26 Jun 2018 18:57:20 +0200 (CEST) Received: from mail-wm0-f48.google.com (mail-wm0-f48.google.com [74.125.82.48]) by dpdk.org (Postfix) with ESMTP id D2B121BE2A for ; Tue, 26 Jun 2018 18:57:05 +0200 (CEST) Received: by mail-wm0-f48.google.com with SMTP id e16-v6so2752538wmd.0 for ; Tue, 26 Jun 2018 09:57:05 -0700 (PDT) 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 :in-reply-to:references; bh=jiFQq/b0N6qwpPp/G+JTyFUUQLrdWExhtKcMvZahrTY=; b=aBbX5dfllxr2uqz5ipAqs84ZhnBwcQDPh9/H/kYPcdiyibII9LMDEORGYU2q8gToBl jSvROA9LgJykt91BcbeK1am9hmFlzHzhSFDl4FAX7scKIr/04QbgroYEX7qw8npMbplM 2d4ZX4o7WTKX1iGIxS0xyfZCnwIlxujF+dhZWRRPM9VXu/9BDKYO4xZwRnT5SFmbXIga 4p3vCHFnbHKvnGeieff5wBsbBV8uDFLhAA9OaLaBJ0SJaDR61/zwCsc5BNPmKtHk9lBT xlWUYLK+X6UKEXTHi2D81lQaULjOlMoctHPOZEskM0SY1qvn9ZQlC2OcxvZOxsOW+0Gt 1bUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=jiFQq/b0N6qwpPp/G+JTyFUUQLrdWExhtKcMvZahrTY=; b=Q9I8GMfyUBADWJuf1wCfzT9P9lGePQF9oZKg59j4se0B8urrD06+t07h0uHAsQuaJT FFZ83ttzmpvdIT/JyfEI9U1mLA3xi5i5jl9FfHoDj8FMAxOeasoZSND3IlHqDhaQb8nv sVAioyas36ZxixPR2e2iGbnYdX+uWITRD+G9ijSPNps6I0/YXS//xMS7AaUebFTH9UAU Q0MVzizHbHmMVjZW4ATeS6WQM4Ty2B9AP73mmEMxlwRL9HCNEinksx5Qgn1jDr+uF0wT smHoCkbNmvIxhMkHfGbGhTyZdvoTM0GXMxO/OmI95m2JkA0EX9TohbkwfyGEz5njdmas EdMw== X-Gm-Message-State: APt69E3zJCeohsCJYL0tV7pCUNjyL5oqBqmJd8Km69bD9VY6jBug2NST 9s36x4j1+6/KJVAn1ZANyNkbsO/c X-Google-Smtp-Source: AAOMgpe2ygQzxKIvVN3UdPWjlyFkNFUckl0H21FnIHqFQeeSULTGrTinINGa+9JGatgWYvV9m5kMNw== X-Received: by 2002:a1c:3a91:: with SMTP id h139-v6mr2330324wma.94.1530032224997; Tue, 26 Jun 2018 09:57:04 -0700 (PDT) Received: from bidouze.dev.6wind.com. (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id p5-v6sm2680880wre.83.2018.06.26.09.57.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Jun 2018 09:57:03 -0700 (PDT) From: Gaetan Rivet To: dev@dpdk.org Cc: Gaetan Rivet Date: Tue, 26 Jun 2018 18:56:15 +0200 Message-Id: <37f7849559bafea9b2e52475a7c30ecad6d7f3a3.1530031921.git.gaetan.rivet@6wind.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v8 12/21] eal/dev: implement device iteration X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Use the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists. Signed-off-by: Gaetan Rivet --- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 5b7956d17..3d486a841 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs; /* spinlock for device callbacks */ static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER; +struct dev_next_ctx { + struct rte_dev_iterator *it; + const char *busstr; + const char *clsstr; +}; + +#define CTX(it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX(ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX(ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX(ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) + static int cmp_detached_dev_name(const struct rte_device *dev, const void *_name) { @@ -398,3 +420,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, get_out: return -rte_errno; } + +static char * +dev_str_sane_copy(const char *str) +{ + size_t end; + char *copy; + + end = strcspn(str, ",/"); + if (str[end] == ',') { + copy = strdup(&str[end + 1]); + } else { + /* '/' or '\0' */ + copy = strdup(""); + } + if (copy == NULL) { + rte_errno = ENOMEM; + } else { + char *slash; + + slash = strchr(copy, '/'); + if (slash != NULL) + slash[0] = '\0'; + } + return copy; +} + +static int +class_next_dev_cmp(const struct rte_class *cls, + const void *ctx) +{ + struct rte_dev_iterator *it; + const char *clsstr = NULL; + void *dev; + + if (cls->dev_iterate == NULL) + return 1; + it = ITCTX(ctx); + clsstr = CLSCTX(ctx); + dev = it->class_device; + /* it->clsstr != NULL means a class + * was specified in the devstr. + */ + if (it->clsstr != NULL && cls != it->cls) + return 1; + /* If an error occurred previously, + * no need to test further. + */ + if (rte_errno != 0) + return -1; + dev = cls->dev_iterate(dev, clsstr, it); + it->class_device = dev; + return dev == NULL; +} + +static int +bus_next_dev_cmp(const struct rte_bus *bus, + const void *ctx) +{ + struct rte_device *dev = NULL; + struct rte_class *cls = NULL; + struct rte_dev_iterator *it; + const char *busstr = NULL; + + if (bus->dev_iterate == NULL) + return 1; + it = ITCTX(ctx); + busstr = BUSCTX(ctx); + dev = it->device; + /* it->busstr != NULL means a bus + * was specified in the devstr. + */ + if (it->busstr != NULL && bus != it->bus) + return 1; + /* If an error occurred previously, + * no need to test further. + */ + if (rte_errno != 0) + return -1; + if (it->clsstr == NULL) { + dev = bus->dev_iterate(dev, busstr, it); + goto end; + } + /* clsstr != NULL */ + if (dev == NULL) { +next_dev_on_bus: + dev = bus->dev_iterate(dev, busstr, it); + it->device = dev; + } + if (dev == NULL) + return 1; + if (it->cls != NULL) + cls = TAILQ_PREV(it->cls, rte_class_list, next); + cls = rte_class_find(cls, class_next_dev_cmp, ctx); + if (cls != NULL) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; + return dev == NULL; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next(struct rte_dev_iterator *it) +{ + struct rte_bus *bus = NULL; + int old_errno = rte_errno; + char *busstr = NULL; + char *clsstr = NULL; + + rte_errno = 0; + if (it->busstr == NULL && it->clsstr == NULL) { + /* Invalid iterator. */ + rte_errno = EINVAL; + return NULL; + } + if (it->bus != NULL) + bus = TAILQ_PREV(it->bus, rte_bus_list, next); + if (it->busstr != NULL) { + busstr = dev_str_sane_copy(it->busstr); + if (busstr == NULL) + goto out; + } + if (it->clsstr != NULL) { + clsstr = dev_str_sane_copy(it->clsstr); + if (clsstr == NULL) + goto out; + } + while ((bus = rte_bus_find(bus, bus_next_dev_cmp, + CTX(it, busstr, clsstr)))) { + if (it->device != NULL) { + it->bus = bus; + goto out; + } + if (it->busstr != NULL || + rte_errno != 0) + break; + } + if (rte_errno == 0) + rte_errno = old_errno; +out: + free(busstr); + free(clsstr); + return it->device; +} diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 7b7bd83bc..1553c0970 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -356,6 +356,32 @@ __rte_experimental int rte_dev_iterator_init(struct rte_dev_iterator *it, const char *str); +/** + * Iterates on a device iterator. + * + * Generates a new rte_device handle corresponding to the next element + * in the list described in comprehension by the iterator. + * + * The next object is returned, and the iterator is updated. + * + * @param it + * Device iterator handle. + * + * @return + * An rte_device handle if found. + * NULL if an error occurred (rte_errno is set). + * NULL if no device could be found (rte_errno is not set). + */ +__rte_experimental +struct rte_device * +rte_dev_iterator_next(struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH(dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index ac04120d6..4cd5ab3df 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -252,6 +252,7 @@ EXPERIMENTAL { rte_dev_event_monitor_start; rte_dev_event_monitor_stop; rte_dev_iterator_init; + rte_dev_iterator_next; rte_devargs_add; rte_devargs_dump; rte_devargs_insert;