From 8b8036a66e3d59ffa58afb8d96fa2c73262155a7 Mon Sep 17 00:00:00 2001 From: Elena Agostini Date: Mon, 8 Nov 2021 18:57:57 +0000 Subject: [PATCH] gpudev: introduce GPU device class library In heterogeneous computing system, processing is not only in the CPU. Some tasks can be delegated to devices working in parallel. The new library gpudev is for dealing with GPGPU computing devices from a DPDK application running on the CPU. The infrastructure is prepared to welcome drivers in drivers/gpu/. Signed-off-by: Elena Agostini Signed-off-by: Thomas Monjalon --- .gitignore | 1 + MAINTAINERS | 7 + app/meson.build | 1 + app/test-gpudev/main.c | 106 +++++++++++ app/test-gpudev/meson.build | 5 + doc/api/doxy-api.conf.in | 1 + doc/guides/conf.py | 8 + doc/guides/gpus/features/default.ini | 10 + doc/guides/gpus/index.rst | 11 ++ doc/guides/gpus/overview.rst | 10 + doc/guides/index.rst | 1 + doc/guides/prog_guide/gpudev.rst | 36 ++++ doc/guides/prog_guide/index.rst | 1 + doc/guides/rel_notes/release_21_11.rst | 4 + drivers/gpu/meson.build | 4 + drivers/meson.build | 1 + lib/gpudev/gpudev.c | 249 +++++++++++++++++++++++++ lib/gpudev/gpudev_driver.h | 67 +++++++ lib/gpudev/meson.build | 10 + lib/gpudev/rte_gpudev.h | 168 +++++++++++++++++ lib/gpudev/version.map | 20 ++ lib/meson.build | 1 + 22 files changed, 722 insertions(+) create mode 100644 app/test-gpudev/main.c create mode 100644 app/test-gpudev/meson.build create mode 100644 doc/guides/gpus/features/default.ini create mode 100644 doc/guides/gpus/index.rst create mode 100644 doc/guides/gpus/overview.rst create mode 100644 doc/guides/prog_guide/gpudev.rst create mode 100644 drivers/gpu/meson.build create mode 100644 lib/gpudev/gpudev.c create mode 100644 lib/gpudev/gpudev_driver.h create mode 100644 lib/gpudev/meson.build create mode 100644 lib/gpudev/rte_gpudev.h create mode 100644 lib/gpudev/version.map diff --git a/.gitignore b/.gitignore index 7ec8688342..b98a43a601 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,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/gpus/overview_feature_table.txt # ignore generated ctags/cscope files cscope.out.po diff --git a/MAINTAINERS b/MAINTAINERS index 3459187e26..e157e12f88 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -467,6 +467,13 @@ M: Bruce Richardson F: examples/dma/ F: doc/guides/sample_app_ug/dma.rst +General-Purpose Graphics Processing Unit (GPU) API - EXPERIMENTAL +M: Elena Agostini +F: lib/gpudev/ +F: doc/guides/prog_guide/gpudev.rst +F: doc/guides/gpus/features/default.ini +F: app/test-gpudev/ + Eventdev API M: Jerin Jacob T: git://dpdk.org/next/dpdk-next-eventdev diff --git a/app/meson.build b/app/meson.build index 986c1a4ad4..310e83076f 100644 --- a/app/meson.build +++ b/app/meson.build @@ -13,6 +13,7 @@ apps = [ 'test-eventdev', 'test-fib', 'test-flow-perf', + 'test-gpudev', 'test-pipeline', 'test-pmd', 'test-regex', diff --git a/app/test-gpudev/main.c b/app/test-gpudev/main.c new file mode 100644 index 0000000000..15b6e4e2a2 --- /dev/null +++ b/app/test-gpudev/main.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum app_args { + ARG_HELP, + ARG_MEMPOOL +}; + +static void +usage(const char *prog_name) +{ + printf("%s [EAL options] --\n", + prog_name); +} + +static void +args_parse(int argc, char **argv) +{ + char **argvopt; + int opt; + int opt_idx; + + static struct option lgopts[] = { + { "help", 0, 0, ARG_HELP}, + /* End of options */ + { 0, 0, 0, 0 } + }; + + argvopt = argv; + while ((opt = getopt_long(argc, argvopt, "", + lgopts, &opt_idx)) != EOF) { + switch (opt) { + case ARG_HELP: + usage(argv[0]); + break; + default: + usage(argv[0]); + rte_exit(EXIT_FAILURE, "Invalid option: %s\n", argv[optind]); + break; + } + } +} + +int +main(int argc, char **argv) +{ + int ret; + int nb_gpus = 0; + int16_t gpu_id = 0; + struct rte_gpu_info ginfo; + + /* Init EAL. */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "EAL init failed\n"); + argc -= ret; + argv += ret; + if (argc > 1) + args_parse(argc, argv); + argc -= ret; + argv += ret; + + nb_gpus = rte_gpu_count_avail(); + printf("\n\nDPDK found %d GPUs:\n", nb_gpus); + RTE_GPU_FOREACH(gpu_id) + { + if (rte_gpu_info_get(gpu_id, &ginfo)) + rte_exit(EXIT_FAILURE, "rte_gpu_info_get error - bye\n"); + + printf("\tGPU ID %d\n\t\tGPU Bus ID %s NUMA node %d Tot memory %.02f MB, Tot processors %d\n", + ginfo.dev_id, + ginfo.name, + ginfo.numa_node, + (((float)ginfo.total_memory)/(float)1024)/(float)1024, + ginfo.processor_count + ); + } + printf("\n\n"); + + /* clean up the EAL */ + rte_eal_cleanup(); + printf("Bye...\n"); + + return EXIT_SUCCESS; +} diff --git a/app/test-gpudev/meson.build b/app/test-gpudev/meson.build new file mode 100644 index 0000000000..17bdef3646 --- /dev/null +++ b/app/test-gpudev/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2021 NVIDIA Corporation & Affiliates + +sources = files('main.c') +deps = ['gpudev', 'ethdev'] diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in index 096ebbaf0d..db2ca9b6ed 100644 --- a/doc/api/doxy-api.conf.in +++ b/doc/api/doxy-api.conf.in @@ -41,6 +41,7 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \ @TOPDIR@/lib/eventdev \ @TOPDIR@/lib/fib \ @TOPDIR@/lib/flow_classify \ + @TOPDIR@/lib/gpudev \ @TOPDIR@/lib/graph \ @TOPDIR@/lib/gro \ @TOPDIR@/lib/gso \ diff --git a/doc/guides/conf.py b/doc/guides/conf.py index 0494b0efe7..e6ce929bc8 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)) @@ -393,6 +396,11 @@ def setup(app): 'Features', 'Features availability in bbdev drivers', 'Feature') + table_file = dirname(__file__) + '/gpus/overview_feature_table.txt' + generate_overview_table(table_file, 1, + 'Features', + 'Features availability in GPU drivers', + 'Feature') if LooseVersion(sphinx_version) < LooseVersion('1.3.1'): print('Upgrade sphinx to version >= 1.3.1 for ' diff --git a/doc/guides/gpus/features/default.ini b/doc/guides/gpus/features/default.ini new file mode 100644 index 0000000000..ec7a545eb7 --- /dev/null +++ b/doc/guides/gpus/features/default.ini @@ -0,0 +1,10 @@ +; +; Features of GPU drivers. +; +; 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/gpus/index.rst b/doc/guides/gpus/index.rst new file mode 100644 index 0000000000..1878423239 --- /dev/null +++ b/doc/guides/gpus/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +General-Purpose Graphics Processing Unit Drivers +================================================ + +.. toctree:: + :maxdepth: 2 + :numbered: + + overview diff --git a/doc/guides/gpus/overview.rst b/doc/guides/gpus/overview.rst new file mode 100644 index 0000000000..4830348818 --- /dev/null +++ b/doc/guides/gpus/overview.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +Overview of GPU Drivers +======================= + +General-Purpose computing on Graphics Processing Unit (GPGPU) +is the use of GPU to perform parallel computation. + +.. include:: overview_feature_table.txt diff --git a/doc/guides/index.rst b/doc/guides/index.rst index 919825992e..5eb5bd9c9a 100644 --- a/doc/guides/index.rst +++ b/doc/guides/index.rst @@ -22,6 +22,7 @@ DPDK documentation vdpadevs/index regexdevs/index dmadevs/index + gpus/index eventdevs/index rawdevs/index mempool/index diff --git a/doc/guides/prog_guide/gpudev.rst b/doc/guides/prog_guide/gpudev.rst new file mode 100644 index 0000000000..6ea7239159 --- /dev/null +++ b/doc/guides/prog_guide/gpudev.rst @@ -0,0 +1,36 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright (c) 2021 NVIDIA Corporation & Affiliates + +General-Purpose Graphics Processing Unit Library +================================================ + +When mixing networking activity with task processing on a GPU device, +there may be the need to put in communication the CPU with the device +in order to manage the memory, synchronize operations, exchange info, etc.. + +By means of the generic GPU interface provided by this library, +it is possible to allocate a chunk of GPU memory and use it +to create a DPDK mempool with external mbufs having the payload +on the GPU memory, enabling any network interface card +(which support this feature like Mellanox NIC) +to directly transmit and receive packets using GPU memory. + +Additionally, this library provides a number of functions +to enhance the dialog between CPU and GPU. + +Out of scope of this library is to provide a wrapper for GPU specific libraries +(e.g. CUDA Toolkit or OpenCL), thus it is not possible to launch workload +on the device or create GPU specific objects +(e.g. CUDA Driver context or CUDA Streams in case of NVIDIA GPUs). + + +Features +-------- + +This library provides a number of features: + +- Interoperability with device-specific library through generic handlers. + + +API Overview +------------ diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 20e5155cf4..7090b5589a 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -28,6 +28,7 @@ Programmer's Guide compressdev regexdev dmadev + gpudev rte_security rawdev link_bonding_poll_mode_drv_lib diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index 8da19c613a..9cf59e73bb 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -101,6 +101,10 @@ New Features Added ``rte_eth_macaddrs_get`` to allow user to retrieve all Ethernet addresses assigned to given ethernet port. +* **Introduced GPU device class with first features:** + + * Device information + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and diff --git a/drivers/gpu/meson.build b/drivers/gpu/meson.build new file mode 100644 index 0000000000..e51ad3381b --- /dev/null +++ b/drivers/gpu/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 34c0276487..d5f4e1c1f2 100644 --- a/drivers/meson.build +++ b/drivers/meson.build @@ -19,6 +19,7 @@ subdirs = [ 'vdpa', # depends on common, bus and mempool. 'event', # depends on common, bus, mempool and net. 'baseband', # depends on common and bus. + 'gpu', # depends on common and bus. ] if meson.is_cross_build() diff --git a/lib/gpudev/gpudev.c b/lib/gpudev/gpudev.c new file mode 100644 index 0000000000..aeb021f2cc --- /dev/null +++ b/lib/gpudev/gpudev.c @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include + +#include "rte_gpudev.h" +#include "gpudev_driver.h" + +/* Logging */ +RTE_LOG_REGISTER_DEFAULT(gpu_logtype, NOTICE); +#define GPU_LOG(level, ...) \ + rte_log(RTE_LOG_ ## level, gpu_logtype, RTE_FMT("gpu: " \ + RTE_FMT_HEAD(__VA_ARGS__, ) "\n", RTE_FMT_TAIL(__VA_ARGS__, ))) + +/* Set any driver error as EPERM */ +#define GPU_DRV_RET(function) \ + ((function != 0) ? -(rte_errno = EPERM) : (rte_errno = 0)) + +/* Array of devices */ +static struct rte_gpu *gpus; +/* Number of currently valid devices */ +static int16_t gpu_max; +/* Number of currently valid devices */ +static int16_t gpu_count; + +int +rte_gpu_init(size_t dev_max) +{ + if (dev_max == 0 || dev_max > INT16_MAX) { + GPU_LOG(ERR, "invalid array size"); + rte_errno = EINVAL; + return -rte_errno; + } + + /* No lock, it must be called before or during first probing. */ + if (gpus != NULL) { + GPU_LOG(ERR, "already initialized"); + rte_errno = EBUSY; + return -rte_errno; + } + + gpus = calloc(dev_max, sizeof(struct rte_gpu)); + if (gpus == NULL) { + GPU_LOG(ERR, "cannot initialize library"); + rte_errno = ENOMEM; + return -rte_errno; + } + + gpu_max = dev_max; + return 0; +} + +uint16_t +rte_gpu_count_avail(void) +{ + return gpu_count; +} + +bool +rte_gpu_is_valid(int16_t dev_id) +{ + if (dev_id >= 0 && dev_id < gpu_max && + gpus[dev_id].state == RTE_GPU_STATE_INITIALIZED) + return true; + return false; +} + +int16_t +rte_gpu_find_next(int16_t dev_id) +{ + if (dev_id < 0) + dev_id = 0; + while (dev_id < gpu_max && + gpus[dev_id].state == RTE_GPU_STATE_UNUSED) + dev_id++; + + if (dev_id >= gpu_max) + return RTE_GPU_ID_NONE; + return dev_id; +} + +static int16_t +gpu_find_free_id(void) +{ + int16_t dev_id; + + for (dev_id = 0; dev_id < gpu_max; dev_id++) { + if (gpus[dev_id].state == RTE_GPU_STATE_UNUSED) + return dev_id; + } + return RTE_GPU_ID_NONE; +} + +static struct rte_gpu * +gpu_get_by_id(int16_t dev_id) +{ + if (!rte_gpu_is_valid(dev_id)) + return NULL; + return &gpus[dev_id]; +} + +struct rte_gpu * +rte_gpu_get_by_name(const char *name) +{ + int16_t dev_id; + struct rte_gpu *dev; + + if (name == NULL) { + rte_errno = EINVAL; + return NULL; + } + + RTE_GPU_FOREACH(dev_id) { + dev = &gpus[dev_id]; + if (strncmp(name, dev->name, RTE_DEV_NAME_MAX_LEN) == 0) + return dev; + } + return NULL; +} + +struct rte_gpu * +rte_gpu_allocate(const char *name) +{ + int16_t dev_id; + struct rte_gpu *dev; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + GPU_LOG(ERR, "only primary process can allocate device"); + rte_errno = EPERM; + return NULL; + } + if (name == NULL) { + GPU_LOG(ERR, "allocate device without a name"); + rte_errno = EINVAL; + return NULL; + } + + /* implicit initialization of library before adding first device */ + if (gpus == NULL && rte_gpu_init(RTE_GPU_DEFAULT_MAX) < 0) + return NULL; + + if (rte_gpu_get_by_name(name) != NULL) { + GPU_LOG(ERR, "device with name %s already exists", name); + rte_errno = EEXIST; + return NULL; + } + dev_id = gpu_find_free_id(); + if (dev_id == RTE_GPU_ID_NONE) { + GPU_LOG(ERR, "reached maximum number of devices"); + rte_errno = ENOENT; + return NULL; + } + + dev = &gpus[dev_id]; + memset(dev, 0, sizeof(*dev)); + + if (rte_strscpy(dev->name, name, RTE_DEV_NAME_MAX_LEN) < 0) { + GPU_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; + + gpu_count++; + GPU_LOG(DEBUG, "new device %s (id %d) of total %d", + name, dev_id, gpu_count); + return dev; +} + +void +rte_gpu_complete_new(struct rte_gpu *dev) +{ + if (dev == NULL) + return; + + dev->state = RTE_GPU_STATE_INITIALIZED; +} + +int +rte_gpu_release(struct rte_gpu *dev) +{ + if (dev == NULL) { + rte_errno = ENODEV; + return -rte_errno; + } + + GPU_LOG(DEBUG, "free device %s (id %d)", + dev->info.name, dev->info.dev_id); + dev->state = RTE_GPU_STATE_UNUSED; + gpu_count--; + + return 0; +} + +int +rte_gpu_close(int16_t dev_id) +{ + int firsterr, binerr; + int *lasterr = &firsterr; + struct rte_gpu *dev; + + dev = gpu_get_by_id(dev_id); + if (dev == NULL) { + GPU_LOG(ERR, "close invalid device ID %d", dev_id); + rte_errno = ENODEV; + return -rte_errno; + } + + if (dev->ops.dev_close != NULL) { + *lasterr = GPU_DRV_RET(dev->ops.dev_close(dev)); + if (*lasterr != 0) + lasterr = &binerr; + } + + *lasterr = rte_gpu_release(dev); + + rte_errno = -firsterr; + return firsterr; +} + +int +rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info) +{ + struct rte_gpu *dev; + + dev = gpu_get_by_id(dev_id); + if (dev == NULL) { + GPU_LOG(ERR, "query invalid device ID %d", dev_id); + rte_errno = ENODEV; + return -rte_errno; + } + if (info == NULL) { + GPU_LOG(ERR, "query without storage"); + rte_errno = EINVAL; + return -rte_errno; + } + + if (dev->ops.dev_info_get == NULL) { + *info = dev->info; + return 0; + } + return GPU_DRV_RET(dev->ops.dev_info_get(dev, info)); +} diff --git a/lib/gpudev/gpudev_driver.h b/lib/gpudev/gpudev_driver.h new file mode 100644 index 0000000000..9e096e3b64 --- /dev/null +++ b/lib/gpudev/gpudev_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_GPUDEV_DRIVER_H +#define RTE_GPUDEV_DRIVER_H + +#include + +#include + +#include "rte_gpudev.h" + +/* Flags indicate current state of device. */ +enum rte_gpu_state { + RTE_GPU_STATE_UNUSED, /* not initialized */ + RTE_GPU_STATE_INITIALIZED, /* initialized */ +}; + +struct rte_gpu; +typedef int (rte_gpu_close_t)(struct rte_gpu *dev); +typedef int (rte_gpu_info_get_t)(struct rte_gpu *dev, struct rte_gpu_info *info); + +struct rte_gpu_ops { + /* Get device info. If NULL, info is just copied. */ + rte_gpu_info_get_t *dev_info_get; + /* Close device. */ + rte_gpu_close_t *dev_close; +}; + +struct rte_gpu { + /* 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_gpu_info info; + /* Driver functions. */ + struct rte_gpu_ops ops; + /* Current state (used or not) in the running process. */ + enum rte_gpu_state state; /* Updated by this library. */ + /* Driver-specific private data for the running process. */ + void *process_private; +} __rte_cache_aligned; + +__rte_internal +struct rte_gpu *rte_gpu_get_by_name(const char *name); + +/* First step of initialization */ +__rte_internal +struct rte_gpu *rte_gpu_allocate(const char *name); + +/* Last step of initialization. */ +__rte_internal +void rte_gpu_complete_new(struct rte_gpu *dev); + +/* Last step of removal. */ +__rte_internal +int rte_gpu_release(struct rte_gpu *dev); + +#endif /* RTE_GPUDEV_DRIVER_H */ diff --git a/lib/gpudev/meson.build b/lib/gpudev/meson.build new file mode 100644 index 0000000000..608154817b --- /dev/null +++ b/lib/gpudev/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2021 NVIDIA Corporation & Affiliates + +headers = files( + 'rte_gpudev.h', +) + +sources = files( + 'gpudev.c', +) diff --git a/lib/gpudev/rte_gpudev.h b/lib/gpudev/rte_gpudev.h new file mode 100644 index 0000000000..eb7cfa8c59 --- /dev/null +++ b/lib/gpudev/rte_gpudev.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#ifndef RTE_GPUDEV_H +#define RTE_GPUDEV_H + +#include +#include +#include + +#include + +/** + * @file + * Generic library to interact with GPU 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_gpu_init() is not called. */ +#define RTE_GPU_DEFAULT_MAX 32 + +/** Empty device ID. */ +#define RTE_GPU_ID_NONE -1 + +/** Store device info. */ +struct rte_gpu_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_GPU_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_gpu_init(size_t dev_max); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Return the number of GPU detected and associated to DPDK. + * + * @return + * The number of available computing devices. + */ +__rte_experimental +uint16_t rte_gpu_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_gpu_is_valid(int16_t dev_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Get the ID of the next valid GPU 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_GPU_ID_NONE if there is none. + */ +__rte_experimental +int16_t rte_gpu_find_next(int16_t dev_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Macro to iterate over all valid GPU devices. + * + * @param dev_id + * The ID of the next possible valid device, usually 0 to iterate all. + */ +#define RTE_GPU_FOREACH(dev_id) \ + for (dev_id = rte_gpu_find_next(0); \ + dev_id > 0; \ + dev_id = rte_gpu_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_gpu_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_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info); + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_GPUDEV_H */ diff --git a/lib/gpudev/version.map b/lib/gpudev/version.map new file mode 100644 index 0000000000..6ac6b327e2 --- /dev/null +++ b/lib/gpudev/version.map @@ -0,0 +1,20 @@ +EXPERIMENTAL { + global: + + # added in 21.11 + rte_gpu_close; + rte_gpu_count_avail; + rte_gpu_find_next; + rte_gpu_info_get; + rte_gpu_init; + rte_gpu_is_valid; +}; + +INTERNAL { + global: + + rte_gpu_allocate; + rte_gpu_complete_new; + rte_gpu_get_by_name; + rte_gpu_release; +}; diff --git a/lib/meson.build b/lib/meson.build index 499d26060f..8537a5ab80 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -34,6 +34,7 @@ libraries = [ 'distributor', 'efd', 'eventdev', + 'gpudev', 'gro', 'gso', 'ip_frag',