From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 19FE8A0A0C; Fri, 30 Jul 2021 15:56:02 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id F3B1D40DDC; Fri, 30 Jul 2021 15:56:01 +0200 (CEST) Received: from new3-smtp.messagingengine.com (new3-smtp.messagingengine.com [66.111.4.229]) by mails.dpdk.org (Postfix) with ESMTP id 13DE34003F for ; Fri, 30 Jul 2021 15:56:01 +0200 (CEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 74260580B57; Fri, 30 Jul 2021 09:56:00 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 30 Jul 2021 09:56:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monjalon.net; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=K8i8dm1sDmZTc ocXfM5rBLJqtqZvru1/YJey02esa0E=; b=wRSVvgPByGKZCs8yeqi03jhvQWtcu rMdAUWvgOIQZrpB0d2Wu+/cwED73NbqRasOA66SMYTJtNCENvNWtmUQmw02s/RFQ AIWj3Otj3MCb+1MHhuquJfwqg5zdJqWBntTWI71OELKfGAFimfqL+/ZAGCxkDnFS jzMZ24xa/uMr9vFFSuvnLPUHgZoPuiX/y7ljcEaaK+Wr2afuazSm0lvPHLCgGqpj PQLV1vwf5jyboGGutBOXlAC6nEwMZDYTMgBB7txMjRi/W0q5rmMtF1Mh0/qH+514 qgWbQ3BQi0KdWZ4Jn8mUACsKud9P4G+/shU+UechNsDRSf9KBf3w/2l9w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=K8i8dm1sDmZTcocXfM5rBLJqtqZvru1/YJey02esa0E=; b=rKg5/TVn RXkdr2jhfCuhWSsV0jbhl1KZl3yvuEmszEF8/oNCttgTiSGr7Quo0COZddw2VewK rCe1To3bAZ3431yOSCUjvXrTJY4ZuY/NIcG1+aBY5caCh0rVNZbIb3vIagwd596g /vxEEzSfVBPrAL/nsw0WZsOzGfGyRqc/pBw+lXIZ0nVwCaTiuL+gYHNPkDm6/cUr iE4Awu70YcXZZHtVVePbQZEd8UGknbUK+0gqMTGrg2nbbeSRsyNjFatlTOzt/R1F Rd+HzRSi51pVk/qdq9aRdNi3RnyK3aymZThfo8e5wUlDuBNzCupyMMocB6zAVz4A kd1Nr1666mUEuA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrheehgdeiiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefhvffufffkofgjfhgggfestdekredtredttdenucfhrhhomhepvfhhohhmrghs ucfoohhnjhgrlhhonhcuoehthhhomhgrshesmhhonhhjrghlohhnrdhnvghtqeenucggtf frrghtthgvrhhnpeeghfeuteeutedthffgteejuefgudeukeejlefgheeiffdtfeffjedv feduiefhtdenucffohhmrghinheptghonhhfrdhinhdpughpughkrdhorhhgnecuvehluh hsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepthhhohhmrghssehm ohhnjhgrlhhonhdrnhgvth X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 30 Jul 2021 09:55:58 -0400 (EDT) From: Thomas Monjalon To: dev@dpdk.org Cc: Stephen Hemminger , David Marchand , Andrew Rybchenko , Haiyue Wang , Honnappa Nagarahalli , Jerin Jacob , Ferruh Yigit , Elena Agostini , Ray Kinsella , Anatoly Burakov Date: Fri, 30 Jul 2021 15:55:27 +0200 Message-Id: <20210730135533.417611-2-thomas@monjalon.net> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210730135533.417611-1-thomas@monjalon.net> References: <20210602203531.2288645-1-thomas@monjalon.net> <20210730135533.417611-1-thomas@monjalon.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [RFC PATCH v2 1/7] hcdev: introduce heterogeneous computing device library X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 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" From: Elena Agostini In heterogeneous computing system, processing is not only in the CPU. Some tasks can be delegated to devices working in parallel. The new library hcdev is for dealing with computing devices from a DPDK application running on the CPU. The infrastructure is prepared to welcome drivers in drivers/hc/. Signed-off-by: Elena Agostini Signed-off-by: Thomas Monjalon --- .gitignore | 1 + MAINTAINERS | 6 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf.in | 1 + doc/guides/conf.py | 8 + doc/guides/hcdevs/features/default.ini | 10 + doc/guides/hcdevs/index.rst | 11 ++ doc/guides/hcdevs/overview.rst | 11 ++ doc/guides/index.rst | 1 + doc/guides/prog_guide/hcdev.rst | 5 + doc/guides/prog_guide/index.rst | 1 + doc/guides/rel_notes/release_21_08.rst | 4 + drivers/hc/meson.build | 4 + drivers/meson.build | 1 + lib/hcdev/hcdev.c | 249 +++++++++++++++++++++++++ lib/hcdev/hcdev_driver.h | 67 +++++++ lib/hcdev/meson.build | 10 + lib/hcdev/rte_hcdev.h | 169 +++++++++++++++++ lib/hcdev/version.map | 20 ++ lib/meson.build | 1 + 20 files changed, 581 insertions(+) create mode 100644 doc/guides/hcdevs/features/default.ini create mode 100644 doc/guides/hcdevs/index.rst create mode 100644 doc/guides/hcdevs/overview.rst create mode 100644 doc/guides/prog_guide/hcdev.rst create mode 100644 drivers/hc/meson.build create mode 100644 lib/hcdev/hcdev.c create mode 100644 lib/hcdev/hcdev_driver.h create mode 100644 lib/hcdev/meson.build create mode 100644 lib/hcdev/rte_hcdev.h create mode 100644 lib/hcdev/version.map diff --git a/.gitignore b/.gitignore index b19c0717e6..97e57e5897 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ doc/guides/compressdevs/overview_feature_table.txt doc/guides/regexdevs/overview_feature_table.txt doc/guides/vdpadevs/overview_feature_table.txt doc/guides/bbdevs/overview_feature_table.txt +doc/guides/hcdevs/overview_feature_table.txt # ignore generated ctags/cscope files cscope.out.po diff --git a/MAINTAINERS b/MAINTAINERS index 8013ba1f14..71e850ae44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -452,6 +452,12 @@ F: app/test-regex/ F: doc/guides/prog_guide/regexdev.rst F: doc/guides/regexdevs/features/default.ini +Heterogeneous Computing API - EXPERIMENTAL +M: Elena Agostini +F: lib/hcdev/ +F: doc/guides/prog_guide/hcdev.rst +F: doc/guides/hcdevs/features/default.ini + Eventdev API M: Jerin Jacob T: git://dpdk.org/next/dpdk-next-eventdev diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 1992107a03..2e5256ccc1 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -21,6 +21,7 @@ The public API headers are grouped by topics: [compressdev] (@ref rte_compressdev.h), [compress] (@ref rte_comp.h), [regexdev] (@ref rte_regexdev.h), + [hcdev] (@ref rte_hcdev.h), [eventdev] (@ref rte_eventdev.h), [event_eth_rx_adapter] (@ref rte_event_eth_rx_adapter.h), [event_eth_tx_adapter] (@ref rte_event_eth_tx_adapter.h), diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in index 325a0195c6..549f373b8a 100644 --- a/doc/api/doxy-api.conf.in +++ b/doc/api/doxy-api.conf.in @@ -44,6 +44,7 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \ @TOPDIR@/lib/gro \ @TOPDIR@/lib/gso \ @TOPDIR@/lib/hash \ + @TOPDIR@/lib/hcdev \ @TOPDIR@/lib/ip_frag \ @TOPDIR@/lib/ipsec \ @TOPDIR@/lib/jobstats \ diff --git a/doc/guides/conf.py b/doc/guides/conf.py index 67d2dd62c7..67ad2c8090 100644 --- a/doc/guides/conf.py +++ b/doc/guides/conf.py @@ -152,6 +152,9 @@ def generate_overview_table(output_filename, table_id, section, table_name, titl name = ini_filename[:-4] name = name.replace('_vf', 'vf') pmd_names.append(name) + if not pmd_names: + # Add an empty column if table is empty (required by RST syntax) + pmd_names.append(' ') # Pad the table header names. max_header_len = len(max(pmd_names, key=len)) @@ -388,6 +391,11 @@ def setup(app): 'Features', 'Features availability in bbdev drivers', 'Feature') + table_file = dirname(__file__) + '/hcdevs/overview_feature_table.txt' + generate_overview_table(table_file, 1, + 'Features', + 'Features availability in hcdev drivers', + 'Feature') if LooseVersion(sphinx_version) < LooseVersion('1.3.1'): print('Upgrade sphinx to version >= 1.3.1 for ' diff --git a/doc/guides/hcdevs/features/default.ini b/doc/guides/hcdevs/features/default.ini new file mode 100644 index 0000000000..f988ee73d4 --- /dev/null +++ b/doc/guides/hcdevs/features/default.ini @@ -0,0 +1,10 @@ +; +; Features of heterogeneous device driver. +; +; This file defines the features that are valid for inclusion in +; the other driver files and also the order that they appear in +; the features table in the documentation. The feature description +; string should not exceed feature_str_len defined in conf.py. +; +[Features] +Get device info = diff --git a/doc/guides/hcdevs/index.rst b/doc/guides/hcdevs/index.rst new file mode 100644 index 0000000000..4c217ec0c2 --- /dev/null +++ b/doc/guides/hcdevs/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +Heterogeneous Computing Device Drivers +====================================== + +.. toctree:: + :maxdepth: 2 + :numbered: + + overview diff --git a/doc/guides/hcdevs/overview.rst b/doc/guides/hcdevs/overview.rst new file mode 100644 index 0000000000..aedce33792 --- /dev/null +++ b/doc/guides/hcdevs/overview.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +Overview of Heterogeneous Computing Drivers +=========================================== + +Heterogeneous computing device may refer to any computing unit +able to process data and to share some memory with the CPU. +Examples are GPU or specialized processor in a SoC. + +.. include:: overview_feature_table.txt diff --git a/doc/guides/index.rst b/doc/guides/index.rst index 857f0363d3..643c52d8f9 100644 --- a/doc/guides/index.rst +++ b/doc/guides/index.rst @@ -21,6 +21,7 @@ DPDK documentation compressdevs/index vdpadevs/index regexdevs/index + hcdevs/index eventdevs/index rawdevs/index mempool/index diff --git a/doc/guides/prog_guide/hcdev.rst b/doc/guides/prog_guide/hcdev.rst new file mode 100644 index 0000000000..0b5bd3cb1c --- /dev/null +++ b/doc/guides/prog_guide/hcdev.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +Heterogeneous Computing Device Library +====================================== diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 2dce507f46..12e7ea3e20 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -27,6 +27,7 @@ Programmer's Guide cryptodev_lib compressdev regexdev + hcdev rte_security rawdev link_bonding_poll_mode_drv_lib diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst index 16bb9ce19e..fb350b4706 100644 --- a/doc/guides/rel_notes/release_21_08.rst +++ b/doc/guides/rel_notes/release_21_08.rst @@ -55,6 +55,10 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Introduced Heterogeneous Computing Device library with first features:** + + * Device information + * **Added auxiliary bus support.** Auxiliary bus provides a way to split function into child-devices diff --git a/drivers/hc/meson.build b/drivers/hc/meson.build new file mode 100644 index 0000000000..e51ad3381b --- /dev/null +++ b/drivers/hc/meson.build @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2021 NVIDIA Corporation & Affiliates + +drivers = [] diff --git a/drivers/meson.build b/drivers/meson.build index bc6f4f567f..b0dbee1b54 100644 --- a/drivers/meson.build +++ b/drivers/meson.build @@ -18,6 +18,7 @@ subdirs = [ 'vdpa', # depends on common, bus and mempool. 'event', # depends on common, bus, mempool and net. 'baseband', # depends on common and bus. + 'hc', # depends on common and bus. ] if meson.is_cross_build() diff --git a/lib/hcdev/hcdev.c b/lib/hcdev/hcdev.c new file mode 100644 index 0000000000..ea587b3713 --- /dev/null +++ b/lib/hcdev/hcdev.c @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include + +#include "rte_hcdev.h" +#include "hcdev_driver.h" + +/* Logging */ +RTE_LOG_REGISTER_DEFAULT(hcdev_logtype, NOTICE); +#define HCDEV_LOG(level, ...) \ + rte_log(RTE_LOG_ ## level, hcdev_logtype, RTE_FMT("hcdev: " \ + RTE_FMT_HEAD(__VA_ARGS__,) "\n", RTE_FMT_TAIL(__VA_ARGS__,))) + +/* Set any driver error as EPERM */ +#define HCDEV_DRV_RET(function) \ + ((function != 0) ? -(rte_errno = EPERM) : (rte_errno = 0)) + +/* Array of devices */ +static struct rte_hcdev *hcdevs; +/* Number of currently valid devices */ +static int16_t hcdev_max; +/* Number of currently valid devices */ +static int16_t hcdev_count; + +int +rte_hcdev_init(size_t dev_max) +{ + if (dev_max == 0 || dev_max > INT16_MAX) { + HCDEV_LOG(ERR, "invalid array size"); + rte_errno = EINVAL; + return -rte_errno; + } + + /* No lock, it must be called before or during first probing. */ + if (hcdevs != NULL) { + HCDEV_LOG(ERR, "already initialized"); + rte_errno = EBUSY; + return -rte_errno; + } + + hcdevs = calloc(dev_max, sizeof(struct rte_hcdev)); + if (hcdevs == NULL) { + HCDEV_LOG(ERR, "cannot initialize library"); + rte_errno = ENOMEM; + return -rte_errno; + } + + hcdev_max = dev_max; + return 0; +} + +uint16_t +rte_hcdev_count_avail(void) +{ + return hcdev_count; +} + +bool +rte_hcdev_is_valid(int16_t dev_id) +{ + if (dev_id >= 0 && dev_id < hcdev_max && + hcdevs[dev_id].state == RTE_HCDEV_STATE_INITIALIZED) + return true; + return false; +} + +int16_t +rte_hcdev_find_next(int16_t dev_id) +{ + if (dev_id < 0) + dev_id = 0; + while (dev_id < hcdev_max && + hcdevs[dev_id].state == RTE_HCDEV_STATE_UNUSED) + dev_id++; + + if (dev_id >= hcdev_max) + return RTE_HCDEV_ID_NONE; + return dev_id; +} + +static int16_t +hcdev_find_free_id(void) +{ + int16_t dev_id; + + for (dev_id = 0; dev_id < hcdev_max; dev_id++) { + if (hcdevs[dev_id].state == RTE_HCDEV_STATE_UNUSED) + return dev_id; + } + return RTE_HCDEV_ID_NONE; +} + +static struct rte_hcdev * +hcdev_get_by_id(int16_t dev_id) +{ + if (!rte_hcdev_is_valid(dev_id)) + return NULL; + return &hcdevs[dev_id]; +} + +struct rte_hcdev * +rte_hcdev_get_by_name(const char *name) +{ + int16_t dev_id; + struct rte_hcdev *dev; + + if (name == NULL) { + rte_errno = EINVAL; + return NULL; + } + + RTE_HCDEV_FOREACH(dev_id) { + dev = &hcdevs[dev_id]; + if (strncmp(name, dev->name, RTE_DEV_NAME_MAX_LEN) == 0) + return dev; + } + return NULL; +} + +struct rte_hcdev * +rte_hcdev_allocate(const char *name) +{ + int16_t dev_id; + struct rte_hcdev *dev; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + HCDEV_LOG(ERR, "only primary process can allocate device"); + rte_errno = EPERM; + return NULL; + } + if (name == NULL) { + HCDEV_LOG(ERR, "allocate device without a name"); + rte_errno = EINVAL; + return NULL; + } + + /* implicit initialization of library before adding first device */ + if (hcdevs == NULL && rte_hcdev_init(RTE_HCDEV_DEFAULT_MAX) < 0) + return NULL; + + if (rte_hcdev_get_by_name(name) != NULL) { + HCDEV_LOG(ERR, "device with name %s already exists", name); + rte_errno = EEXIST; + return NULL; + } + dev_id = hcdev_find_free_id(); + if (dev_id == RTE_HCDEV_ID_NONE) { + HCDEV_LOG(ERR, "reached maximum number of devices"); + rte_errno = ENOENT; + return NULL; + } + + dev = &hcdevs[dev_id]; + memset(dev, 0, sizeof(*dev)); + + if (rte_strscpy(dev->name, name, RTE_DEV_NAME_MAX_LEN) < 0) { + HCDEV_LOG(ERR, "device name too long: %s", name); + rte_errno = ENAMETOOLONG; + return NULL; + } + dev->info.name = dev->name; + dev->info.dev_id = dev_id; + dev->info.numa_node = -1; + + hcdev_count++; + HCDEV_LOG(DEBUG, "new device %s (id %d) of total %d", + name, dev_id, hcdev_count); + return dev; +} + +void +rte_hcdev_complete_new(struct rte_hcdev *dev) +{ + if (dev == NULL) + return; + + dev->state = RTE_HCDEV_STATE_INITIALIZED; +} + +int +rte_hcdev_release(struct rte_hcdev *dev) +{ + if (dev == NULL) { + rte_errno = ENODEV; + return -rte_errno; + } + + HCDEV_LOG(DEBUG, "free device %s (id %d)", + dev->info.name, dev->info.dev_id); + dev->state = RTE_HCDEV_STATE_UNUSED; + hcdev_count--; + + return 0; +} + +int +rte_hcdev_close(int16_t dev_id) +{ + int firsterr, binerr; + int *lasterr = &firsterr; + struct rte_hcdev *dev; + + dev = hcdev_get_by_id(dev_id); + if (dev == NULL) { + HCDEV_LOG(ERR, "close invalid device ID %d", dev_id); + rte_errno = ENODEV; + return -rte_errno; + } + + if (dev->ops.dev_close != NULL) { + *lasterr = HCDEV_DRV_RET(dev->ops.dev_close(dev)); + if (*lasterr != 0) + lasterr = &binerr; + } + + *lasterr = rte_hcdev_release(dev); + + rte_errno = -firsterr; + return firsterr; +} + +int +rte_hcdev_info_get(int16_t dev_id, struct rte_hcdev_info *info) +{ + struct rte_hcdev *dev; + + dev = hcdev_get_by_id(dev_id); + if (dev == NULL) { + HCDEV_LOG(ERR, "query invalid device ID %d", dev_id); + rte_errno = ENODEV; + return -rte_errno; + } + if (info == NULL) { + HCDEV_LOG(ERR, "query without storage"); + rte_errno = EINVAL; + return -rte_errno; + } + + if (dev->ops.dev_info_get == NULL) { + *info = dev->info; + return 0; + } + return HCDEV_DRV_RET(dev->ops.dev_info_get(dev, info)); +} diff --git a/lib/hcdev/hcdev_driver.h b/lib/hcdev/hcdev_driver.h new file mode 100644 index 0000000000..ca23cb9b9f --- /dev/null +++ b/lib/hcdev/hcdev_driver.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +/* + * This header file must be included only by drivers. + * It is considered internal, i.e. hidden for the application. + * The prefix rte_ is used to avoid namespace clash in drivers. + */ + +#ifndef RTE_HCDEV_DRIVER_H +#define RTE_HCDEV_DRIVER_H + +#include + +#include + +#include "rte_hcdev.h" + +/* Flags indicate current state of device. */ +enum rte_hcdev_state { + RTE_HCDEV_STATE_UNUSED, /* not initialized */ + RTE_HCDEV_STATE_INITIALIZED, /* initialized */ +}; + +struct rte_hcdev; +typedef int (rte_hcdev_close_t)(struct rte_hcdev *dev); +typedef int (rte_hcdev_info_get_t)(struct rte_hcdev *dev, struct rte_hcdev_info *info); + +struct rte_hcdev_ops { + /* Get device info. If NULL, info is just copied. */ + rte_hcdev_info_get_t *dev_info_get; + /* Close device. */ + rte_hcdev_close_t *dev_close; +}; + +struct rte_hcdev { + /* Backing device. */ + struct rte_device *device; + /* Unique identifier name. */ + char name[RTE_DEV_NAME_MAX_LEN]; /* Updated by this library. */ + /* Device info structure. */ + struct rte_hcdev_info info; + /* Driver functions. */ + struct rte_hcdev_ops ops; + /* Current state (used or not) in the running process. */ + enum rte_hcdev_state state; /* Updated by this library. */ + /* Driver-specific private data for the running process. */ + void *process_private; +} __rte_cache_aligned; + +__rte_internal +struct rte_hcdev *rte_hcdev_get_by_name(const char *name); + +/* First step of initialization */ +__rte_internal +struct rte_hcdev *rte_hcdev_allocate(const char *name); + +/* Last step of initialization. */ +__rte_internal +void rte_hcdev_complete_new(struct rte_hcdev *dev); + +/* Last step of removal. */ +__rte_internal +int rte_hcdev_release(struct rte_hcdev *dev); + +#endif /* RTE_HCDEV_DRIVER_H */ diff --git a/lib/hcdev/meson.build b/lib/hcdev/meson.build new file mode 100644 index 0000000000..565c3cb623 --- /dev/null +++ b/lib/hcdev/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2021 NVIDIA Corporation & Affiliates + +headers = files( + 'rte_hcdev.h', +) + +sources = files( + 'hcdev.c', +) diff --git a/lib/hcdev/rte_hcdev.h b/lib/hcdev/rte_hcdev.h new file mode 100644 index 0000000000..83f58193c1 --- /dev/null +++ b/lib/hcdev/rte_hcdev.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#ifndef RTE_HCDEV_H +#define RTE_HCDEV_H + +#include +#include +#include + +#include + +/** + * @file + * Generic library to interact with heterogeneous computing device. + * + * The API is not thread-safe. + * Device management must be done by a single thread. + * + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum number of devices if rte_hcdev_init() is not called. */ +#define RTE_HCDEV_DEFAULT_MAX 32 + +/** Empty device ID. */ +#define RTE_HCDEV_ID_NONE -1 + +/** Store device info. */ +struct rte_hcdev_info { + /** Unique identifier name. */ + const char *name; + /** Device ID. */ + int16_t dev_id; + /** Total processors available on device. */ + uint32_t processor_count; + /** Total memory available on device. */ + size_t total_memory; + /* Local NUMA memory ID. -1 if unknown. */ + int16_t numa_node; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Initialize the device array before probing devices. + * If not called, the maximum of probed devices is RTE_HCDEV_DEFAULT_MAX. + * + * @param dev_max + * Maximum number of devices. + * + * @return + * 0 on success, -rte_errno otherwise: + * - ENOMEM if out of memory + * - EINVAL if 0 size + * - EBUSY if already initialized + */ +__rte_experimental +int rte_hcdev_init(size_t dev_max); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Return the number of heterogeneous computing devices detected + * and associated to DPDK. + * + * @return + * The number of available computing devices. + */ +__rte_experimental +uint16_t rte_hcdev_count_avail(void); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Check if the device is valid and initialized in DPDK. + * + * @param dev_id + * The input device ID. + * + * @return + * - True if dev_id is a valid and initialized computing device. + * - False otherwise. + */ +__rte_experimental +bool rte_hcdev_is_valid(int16_t dev_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Get the ID of the next valid computing device initialized in DPDK. + * + * @param dev_id + * The initial device ID to start the research. + * + * @return + * Next device ID corresponding to a valid and initialized computing device, + * RTE_HCDEV_ID_NONE if there is none. + */ +__rte_experimental +int16_t rte_hcdev_find_next(int16_t dev_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Macro to iterate over all valid computing devices. + * + * @param dev_id + * The ID of the next possible valid device, usually 0 to iterate all. + */ +#define RTE_HCDEV_FOREACH(dev_id) \ + for (dev_id = rte_hcdev_find_next(0); \ + dev_id > 0; \ + dev_id = rte_hcdev_find_next(dev_id + 1)) + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Close device. + * All resources are released. + * + * @param dev_id + * Device ID to close. + * + * @return + * 0 on success, -rte_errno otherwise: + * - ENODEV if invalid dev_id + * - EPERM if driver error + */ +__rte_experimental +int rte_hcdev_close(int16_t dev_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Return device specific info. + * + * @param dev_id + * Device ID to get info. + * @param info + * Memory structure to fill with the info. + * + * @return + * 0 on success, -rte_errno otherwise: + * - ENODEV if invalid dev_id + * - EINVAL if NULL info + * - EPERM if driver error + */ +__rte_experimental +int rte_hcdev_info_get(int16_t dev_id, struct rte_hcdev_info *info); + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_HCDEV_H */ diff --git a/lib/hcdev/version.map b/lib/hcdev/version.map new file mode 100644 index 0000000000..bc6dae6de7 --- /dev/null +++ b/lib/hcdev/version.map @@ -0,0 +1,20 @@ +EXPERIMENTAL { + global: + + # added in 21.11 + rte_hcdev_close; + rte_hcdev_count_avail; + rte_hcdev_find_next; + rte_hcdev_info_get; + rte_hcdev_init; + rte_hcdev_is_valid; +}; + +INTERNAL { + global: + + rte_hcdev_allocate; + rte_hcdev_complete_new; + rte_hcdev_get_by_name; + rte_hcdev_release; +}; diff --git a/lib/meson.build b/lib/meson.build index 1673ca4323..3239182c03 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -35,6 +35,7 @@ libraries = [ 'eventdev', 'gro', 'gso', + 'hcdev', 'ip_frag', 'jobstats', 'kni', -- 2.31.1