1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2021 NVIDIA Corporation & Affiliates 3 */ 4 5 #ifndef RTE_GPUDEV_H 6 #define RTE_GPUDEV_H 7 8 #include <stddef.h> 9 #include <stdint.h> 10 #include <stdbool.h> 11 12 #include <rte_mbuf.h> 13 #include <rte_bitops.h> 14 #include <rte_compat.h> 15 16 /** 17 * @file 18 * Generic library to interact with GPU computing device. 19 * 20 * The API is not thread-safe. 21 * Device management must be done by a single thread. 22 * 23 * @warning 24 * @b EXPERIMENTAL: this API may change without prior notice. 25 */ 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 /** Maximum number of devices if rte_gpu_init() is not called. */ 32 #define RTE_GPU_DEFAULT_MAX 32 33 34 /** Empty device ID. */ 35 #define RTE_GPU_ID_NONE -1 36 /** Catch-all device ID. */ 37 #define RTE_GPU_ID_ANY INT16_MIN 38 39 /** Catch-all callback data. */ 40 #define RTE_GPU_CALLBACK_ANY_DATA ((void *)-1) 41 42 /** Access variable as volatile. */ 43 #define RTE_GPU_VOLATILE(x) (*(volatile typeof(x) *)&(x)) 44 45 /** Max number of packets per communication list. */ 46 #define RTE_GPU_COMM_LIST_PKTS_MAX 1024 47 48 /** Store device info. */ 49 struct rte_gpu_info { 50 /** Unique identifier name. */ 51 const char *name; 52 /** Opaque handler of the device context. */ 53 uint64_t context; 54 /** Device ID. */ 55 int16_t dev_id; 56 /** ID of the parent device, RTE_GPU_ID_NONE if no parent */ 57 int16_t parent; 58 /** Total processors available on device. */ 59 uint32_t processor_count; 60 /** Total memory available on device. */ 61 size_t total_memory; 62 /* Local NUMA memory ID. -1 if unknown. */ 63 int16_t numa_node; 64 }; 65 66 /** Flags passed in notification callback. */ 67 enum rte_gpu_event { 68 /** Device is just initialized. */ 69 RTE_GPU_EVENT_NEW, 70 /** Device is going to be released. */ 71 RTE_GPU_EVENT_DEL, 72 }; 73 74 /** Prototype of event callback function. */ 75 typedef void (rte_gpu_callback_t)(int16_t dev_id, 76 enum rte_gpu_event event, void *user_data); 77 78 /** Memory where communication flag is allocated. */ 79 enum rte_gpu_comm_flag_type { 80 /** Allocate flag on CPU memory visible from device. */ 81 RTE_GPU_COMM_FLAG_CPU = 0, 82 }; 83 84 /** Communication flag to coordinate CPU with the device. */ 85 struct rte_gpu_comm_flag { 86 /** Device that will use the device flag. */ 87 uint16_t dev_id; 88 /** Pointer to flag memory area. */ 89 uint32_t *ptr; 90 /** Type of memory used to allocate the flag. */ 91 enum rte_gpu_comm_flag_type mtype; 92 }; 93 94 /** List of packets shared among CPU and device. */ 95 struct rte_gpu_comm_pkt { 96 /** Address of the packet in memory (e.g. mbuf->buf_addr). */ 97 uintptr_t addr; 98 /** Size in byte of the packet. */ 99 size_t size; 100 }; 101 102 /** Possible status for the list of packets shared among CPU and device. */ 103 enum rte_gpu_comm_list_status { 104 /** Packet list can be filled with new mbufs, no one is using it. */ 105 RTE_GPU_COMM_LIST_FREE = 0, 106 /** Packet list has been filled with new mbufs and it's ready to be used .*/ 107 RTE_GPU_COMM_LIST_READY, 108 /** Packet list has been processed, it's ready to be freed. */ 109 RTE_GPU_COMM_LIST_DONE, 110 /** Some error occurred during packet list processing. */ 111 RTE_GPU_COMM_LIST_ERROR, 112 }; 113 114 /** 115 * Communication list holding a number of lists of packets 116 * each having a status flag. 117 */ 118 struct rte_gpu_comm_list { 119 /** Device that will use the communication list. */ 120 uint16_t dev_id; 121 /** List of mbufs populated by the CPU with a set of mbufs. */ 122 struct rte_mbuf **mbufs; 123 /** List of packets populated by the CPU with a set of mbufs info. */ 124 struct rte_gpu_comm_pkt *pkt_list; 125 /** Number of packets in the list. */ 126 uint32_t num_pkts; 127 /** Status of the list. */ 128 enum rte_gpu_comm_list_status status; 129 }; 130 131 /** 132 * @warning 133 * @b EXPERIMENTAL: this API may change without prior notice. 134 * 135 * Initialize the device array before probing devices. 136 * If not called, the maximum of probed devices is RTE_GPU_DEFAULT_MAX. 137 * 138 * @param dev_max 139 * Maximum number of devices. 140 * 141 * @return 142 * 0 on success, -rte_errno otherwise: 143 * - ENOMEM if out of memory 144 * - EINVAL if 0 size 145 * - EBUSY if already initialized 146 */ 147 __rte_experimental 148 int rte_gpu_init(size_t dev_max); 149 150 /** 151 * @warning 152 * @b EXPERIMENTAL: this API may change without prior notice. 153 * 154 * Return the number of GPU detected and associated to DPDK. 155 * 156 * @return 157 * The number of available computing devices. 158 */ 159 __rte_experimental 160 uint16_t rte_gpu_count_avail(void); 161 162 /** 163 * @warning 164 * @b EXPERIMENTAL: this API may change without prior notice. 165 * 166 * Check if the device is valid and initialized in DPDK. 167 * 168 * @param dev_id 169 * The input device ID. 170 * 171 * @return 172 * - True if dev_id is a valid and initialized computing device. 173 * - False otherwise. 174 */ 175 __rte_experimental 176 bool rte_gpu_is_valid(int16_t dev_id); 177 178 /** 179 * @warning 180 * @b EXPERIMENTAL: this API may change without prior notice. 181 * 182 * Create a virtual device representing a context in the parent device. 183 * 184 * @param name 185 * Unique string to identify the device. 186 * @param parent 187 * Device ID of the parent. 188 * @param child_context 189 * Opaque context handler. 190 * 191 * @return 192 * Device ID of the new created child, -rte_errno otherwise: 193 * - EINVAL if empty name 194 * - ENAMETOOLONG if long name 195 * - EEXIST if existing device name 196 * - ENODEV if invalid parent 197 * - EPERM if secondary process 198 * - ENOENT if too many devices 199 * - ENOMEM if out of space 200 */ 201 __rte_experimental 202 int16_t rte_gpu_add_child(const char *name, 203 int16_t parent, uint64_t child_context); 204 205 /** 206 * @warning 207 * @b EXPERIMENTAL: this API may change without prior notice. 208 * 209 * Get the ID of the next valid GPU initialized in DPDK. 210 * 211 * @param dev_id 212 * The initial device ID to start the research. 213 * @param parent 214 * The device ID of the parent. 215 * RTE_GPU_ID_NONE means no parent. 216 * RTE_GPU_ID_ANY means no or any parent. 217 * 218 * @return 219 * Next device ID corresponding to a valid and initialized computing device, 220 * RTE_GPU_ID_NONE if there is none. 221 */ 222 __rte_experimental 223 int16_t rte_gpu_find_next(int16_t dev_id, int16_t parent); 224 225 /** 226 * @warning 227 * @b EXPERIMENTAL: this API may change without prior notice. 228 * 229 * Macro to iterate over all valid GPU devices. 230 * 231 * @param dev_id 232 * The ID of the next possible valid device, usually 0 to iterate all. 233 */ 234 #define RTE_GPU_FOREACH(dev_id) \ 235 RTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_ANY) 236 237 /** 238 * @warning 239 * @b EXPERIMENTAL: this API may change without prior notice. 240 * 241 * Macro to iterate over all valid computing devices having no parent. 242 * 243 * @param dev_id 244 * The ID of the next possible valid device, usually 0 to iterate all. 245 */ 246 #define RTE_GPU_FOREACH_PARENT(dev_id) \ 247 RTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_NONE) 248 249 /** 250 * @warning 251 * @b EXPERIMENTAL: this API may change without prior notice. 252 * 253 * Macro to iterate over all valid children of a computing device parent. 254 * 255 * @param dev_id 256 * The ID of the next possible valid device, usually 0 to iterate all. 257 * @param parent 258 * The device ID of the parent. 259 */ 260 #define RTE_GPU_FOREACH_CHILD(dev_id, parent) \ 261 for (dev_id = rte_gpu_find_next(0, parent); \ 262 dev_id >= 0; \ 263 dev_id = rte_gpu_find_next(dev_id + 1, parent)) 264 265 /** 266 * @warning 267 * @b EXPERIMENTAL: this API may change without prior notice. 268 * 269 * Close device or child context. 270 * All resources are released. 271 * 272 * @param dev_id 273 * Device ID to close. 274 * 275 * @return 276 * 0 on success, -rte_errno otherwise: 277 * - ENODEV if invalid dev_id 278 * - EPERM if driver error 279 */ 280 __rte_experimental 281 int rte_gpu_close(int16_t dev_id); 282 283 /** 284 * @warning 285 * @b EXPERIMENTAL: this API may change without prior notice. 286 * 287 * Register a function as event callback. 288 * A function may be registered multiple times for different events. 289 * 290 * @param dev_id 291 * Device ID to get notified about. 292 * RTE_GPU_ID_ANY means all devices. 293 * @param event 294 * Device event to be registered for. 295 * @param function 296 * Callback function to be called on event. 297 * @param user_data 298 * Optional parameter passed in the callback. 299 * 300 * @return 301 * 0 on success, -rte_errno otherwise: 302 * - ENODEV if invalid dev_id 303 * - EINVAL if NULL function 304 * - ENOMEM if out of memory 305 */ 306 __rte_experimental 307 int rte_gpu_callback_register(int16_t dev_id, enum rte_gpu_event event, 308 rte_gpu_callback_t *function, void *user_data); 309 310 /** 311 * @warning 312 * @b EXPERIMENTAL: this API may change without prior notice. 313 * 314 * Unregister for an event. 315 * 316 * @param dev_id 317 * Device ID to be silenced. 318 * RTE_GPU_ID_ANY means all devices. 319 * @param event 320 * Registered event. 321 * @param function 322 * Registered function. 323 * @param user_data 324 * Optional parameter as registered. 325 * RTE_GPU_CALLBACK_ANY_DATA is a catch-all. 326 * 327 * @return 328 * 0 on success, -rte_errno otherwise: 329 * - ENODEV if invalid dev_id 330 * - EINVAL if NULL function 331 */ 332 __rte_experimental 333 int rte_gpu_callback_unregister(int16_t dev_id, enum rte_gpu_event event, 334 rte_gpu_callback_t *function, void *user_data); 335 336 /** 337 * @warning 338 * @b EXPERIMENTAL: this API may change without prior notice. 339 * 340 * Return device specific info. 341 * 342 * @param dev_id 343 * Device ID to get info. 344 * @param info 345 * Memory structure to fill with the info. 346 * 347 * @return 348 * 0 on success, -rte_errno otherwise: 349 * - ENODEV if invalid dev_id 350 * - EINVAL if NULL info 351 * - EPERM if driver error 352 */ 353 __rte_experimental 354 int rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info); 355 356 /** 357 * @warning 358 * @b EXPERIMENTAL: this API may change without prior notice. 359 * 360 * Allocate a chunk of memory in the device. 361 * 362 * @param dev_id 363 * Device ID requiring allocated memory. 364 * @param size 365 * Number of bytes to allocate. 366 * Requesting 0 will do nothing. 367 * 368 * @return 369 * A pointer to the allocated memory, otherwise NULL and rte_errno is set: 370 * - ENODEV if invalid dev_id 371 * - EINVAL if reserved flags 372 * - ENOTSUP if operation not supported by the driver 373 * - E2BIG if size is higher than limit 374 * - ENOMEM if out of space 375 * - EPERM if driver error 376 */ 377 __rte_experimental 378 void *rte_gpu_mem_alloc(int16_t dev_id, size_t size) 379 __rte_alloc_size(2); 380 381 /** 382 * @warning 383 * @b EXPERIMENTAL: this API may change without prior notice. 384 * 385 * Deallocate a chunk of memory allocated with rte_gpu_mem_alloc(). 386 * 387 * @param dev_id 388 * Reference device ID. 389 * @param ptr 390 * Pointer to the memory area to be deallocated. 391 * NULL is a no-op accepted value. 392 * 393 * @return 394 * 0 on success, -rte_errno otherwise: 395 * - ENODEV if invalid dev_id 396 * - ENOTSUP if operation not supported by the driver 397 * - EPERM if driver error 398 */ 399 __rte_experimental 400 int rte_gpu_mem_free(int16_t dev_id, void *ptr); 401 402 /** 403 * @warning 404 * @b EXPERIMENTAL: this API may change without prior notice. 405 * 406 * Register a chunk of memory on the CPU usable by the device. 407 * 408 * @param dev_id 409 * Device ID requiring allocated memory. 410 * @param size 411 * Number of bytes to allocate. 412 * Requesting 0 will do nothing. 413 * @param ptr 414 * Pointer to the memory area to be registered. 415 * NULL is a no-op accepted value. 416 417 * @return 418 * A pointer to the allocated memory, otherwise NULL and rte_errno is set: 419 * - ENODEV if invalid dev_id 420 * - EINVAL if reserved flags 421 * - ENOTSUP if operation not supported by the driver 422 * - E2BIG if size is higher than limit 423 * - ENOMEM if out of space 424 * - EPERM if driver error 425 */ 426 __rte_experimental 427 int rte_gpu_mem_register(int16_t dev_id, size_t size, void *ptr); 428 429 /** 430 * @warning 431 * @b EXPERIMENTAL: this API may change without prior notice. 432 * 433 * Deregister a chunk of memory previously registered with rte_gpu_mem_register() 434 * 435 * @param dev_id 436 * Reference device ID. 437 * @param ptr 438 * Pointer to the memory area to be unregistered. 439 * NULL is a no-op accepted value. 440 * 441 * @return 442 * 0 on success, -rte_errno otherwise: 443 * - ENODEV if invalid dev_id 444 * - ENOTSUP if operation not supported by the driver 445 * - EPERM if driver error 446 */ 447 __rte_experimental 448 int rte_gpu_mem_unregister(int16_t dev_id, void *ptr); 449 450 /** 451 * @warning 452 * @b EXPERIMENTAL: this API may change without prior notice. 453 * 454 * Enforce a GPU write memory barrier. 455 * 456 * @param dev_id 457 * Reference device ID. 458 * 459 * @return 460 * 0 on success, -rte_errno otherwise: 461 * - ENODEV if invalid dev_id 462 * - ENOTSUP if operation not supported by the driver 463 * - EPERM if driver error 464 */ 465 __rte_experimental 466 int rte_gpu_wmb(int16_t dev_id); 467 468 /** 469 * @warning 470 * @b EXPERIMENTAL: this API may change without prior notice. 471 * 472 * Create a communication flag that can be shared 473 * between CPU threads and device workload to exchange some status info 474 * (e.g. work is done, processing can start, etc..). 475 * 476 * @param dev_id 477 * Reference device ID. 478 * @param devflag 479 * Pointer to the memory area of the devflag structure. 480 * @param mtype 481 * Type of memory to allocate the communication flag. 482 * 483 * @return 484 * 0 on success, -rte_errno otherwise: 485 * - ENODEV if invalid dev_id 486 * - EINVAL if invalid inputs 487 * - ENOTSUP if operation not supported by the driver 488 * - ENOMEM if out of space 489 * - EPERM if driver error 490 */ 491 __rte_experimental 492 int rte_gpu_comm_create_flag(uint16_t dev_id, 493 struct rte_gpu_comm_flag *devflag, 494 enum rte_gpu_comm_flag_type mtype); 495 496 /** 497 * @warning 498 * @b EXPERIMENTAL: this API may change without prior notice. 499 * 500 * Deallocate a communication flag. 501 * 502 * @param devflag 503 * Pointer to the memory area of the devflag structure. 504 * 505 * @return 506 * 0 on success, -rte_errno otherwise: 507 * - ENODEV if invalid dev_id 508 * - EINVAL if NULL devflag 509 * - ENOTSUP if operation not supported by the driver 510 * - EPERM if driver error 511 */ 512 __rte_experimental 513 int rte_gpu_comm_destroy_flag(struct rte_gpu_comm_flag *devflag); 514 515 /** 516 * @warning 517 * @b EXPERIMENTAL: this API may change without prior notice. 518 * 519 * Set the value of a communication flag as the input value. 520 * Flag memory area is treated as volatile. 521 * The flag must have been allocated with RTE_GPU_COMM_FLAG_CPU. 522 * 523 * @param devflag 524 * Pointer to the memory area of the devflag structure. 525 * @param val 526 * Value to set in the flag. 527 * 528 * @return 529 * 0 on success, -rte_errno otherwise: 530 * - EINVAL if invalid input params 531 */ 532 __rte_experimental 533 int rte_gpu_comm_set_flag(struct rte_gpu_comm_flag *devflag, 534 uint32_t val); 535 536 /** 537 * @warning 538 * @b EXPERIMENTAL: this API may change without prior notice. 539 * 540 * Get the value of the communication flag. 541 * Flag memory area is treated as volatile. 542 * The flag must have been allocated with RTE_GPU_COMM_FLAG_CPU. 543 * 544 * @param devflag 545 * Pointer to the memory area of the devflag structure. 546 * @param val 547 * Flag output value. 548 * 549 * @return 550 * 0 on success, -rte_errno otherwise: 551 * - EINVAL if invalid input params 552 */ 553 __rte_experimental 554 int rte_gpu_comm_get_flag_value(struct rte_gpu_comm_flag *devflag, 555 uint32_t *val); 556 557 /** 558 * @warning 559 * @b EXPERIMENTAL: this API may change without prior notice. 560 * 561 * Create a communication list that can be used to share packets 562 * between CPU and device. 563 * Each element of the list contains: 564 * - a packet list of RTE_GPU_COMM_LIST_PKTS_MAX elements 565 * - number of packets in the list 566 * - a status flag to communicate if the packet list is FREE, 567 * READY to be processed, DONE with processing. 568 * 569 * The list is allocated in CPU-visible memory. 570 * At creation time, every list is in FREE state. 571 * 572 * @param dev_id 573 * Reference device ID. 574 * @param num_comm_items 575 * Number of items in the communication list. 576 * 577 * @return 578 * A pointer to the allocated list, otherwise NULL and rte_errno is set: 579 * - EINVAL if invalid input params 580 */ 581 __rte_experimental 582 struct rte_gpu_comm_list *rte_gpu_comm_create_list(uint16_t dev_id, 583 uint32_t num_comm_items); 584 585 /** 586 * @warning 587 * @b EXPERIMENTAL: this API may change without prior notice. 588 * 589 * Destroy a communication list. 590 * 591 * @param comm_list 592 * Communication list to be destroyed. 593 * @param num_comm_items 594 * Number of items in the communication list. 595 * 596 * @return 597 * 0 on success, -rte_errno otherwise: 598 * - EINVAL if invalid input params 599 */ 600 __rte_experimental 601 int rte_gpu_comm_destroy_list(struct rte_gpu_comm_list *comm_list, 602 uint32_t num_comm_items); 603 604 /** 605 * @warning 606 * @b EXPERIMENTAL: this API may change without prior notice. 607 * 608 * Populate the packets list of the communication item 609 * with info from a list of mbufs. 610 * Status flag of that packet list is set to READY. 611 * 612 * @param comm_list_item 613 * Communication list item to fill. 614 * @param mbufs 615 * List of mbufs. 616 * @param num_mbufs 617 * Number of mbufs. 618 * 619 * @return 620 * 0 on success, -rte_errno otherwise: 621 * - EINVAL if invalid input params 622 * - ENOTSUP if mbufs are chained (multiple segments) 623 */ 624 __rte_experimental 625 int rte_gpu_comm_populate_list_pkts(struct rte_gpu_comm_list *comm_list_item, 626 struct rte_mbuf **mbufs, uint32_t num_mbufs); 627 628 /** 629 * @warning 630 * @b EXPERIMENTAL: this API may change without prior notice. 631 * 632 * Reset a communication list item to the original state. 633 * The status flag set to FREE and mbufs are returned to the pool. 634 * 635 * @param comm_list_item 636 * Communication list item to reset. 637 * 638 * @return 639 * 0 on success, -rte_errno otherwise: 640 * - EINVAL if invalid input params 641 */ 642 __rte_experimental 643 int rte_gpu_comm_cleanup_list(struct rte_gpu_comm_list *comm_list_item); 644 645 #ifdef __cplusplus 646 } 647 #endif 648 649 #endif /* RTE_GPUDEV_H */ 650