1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #ifndef _RTE_INTERRUPTS_H_ 6 #define _RTE_INTERRUPTS_H_ 7 8 #include <stdbool.h> 9 10 #include <rte_bitops.h> 11 #include <rte_common.h> 12 #include <rte_compat.h> 13 #include <rte_epoll.h> 14 15 /** 16 * @file 17 * 18 * The RTE interrupt interface provides functions to register/unregister 19 * callbacks for a specific interrupt. 20 */ 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 /** Interrupt handle */ 27 struct rte_intr_handle; 28 29 /** Interrupt instance allocation flags 30 * @see rte_intr_instance_alloc 31 */ 32 33 /** Interrupt instance will not be shared between primary and secondary processes. */ 34 #define RTE_INTR_INSTANCE_F_PRIVATE UINT32_C(0) 35 /** Interrupt instance will be shared between primary and secondary processes. */ 36 #define RTE_INTR_INSTANCE_F_SHARED RTE_BIT32(0) 37 38 #define RTE_MAX_RXTX_INTR_VEC_ID 512 39 #define RTE_INTR_VEC_ZERO_OFFSET 0 40 #define RTE_INTR_VEC_RXTX_OFFSET 1 41 42 /** 43 * The interrupt source type, e.g. UIO, VFIO, ALARM etc. 44 */ 45 enum rte_intr_handle_type { 46 RTE_INTR_HANDLE_UNKNOWN = 0, /**< generic unknown handle */ 47 RTE_INTR_HANDLE_UIO, /**< uio device handle */ 48 RTE_INTR_HANDLE_UIO_INTX, /**< uio generic handle */ 49 RTE_INTR_HANDLE_VFIO_LEGACY, /**< vfio device handle (legacy) */ 50 RTE_INTR_HANDLE_VFIO_MSI, /**< vfio device handle (MSI) */ 51 RTE_INTR_HANDLE_VFIO_MSIX, /**< vfio device handle (MSIX) */ 52 RTE_INTR_HANDLE_ALARM, /**< alarm handle */ 53 RTE_INTR_HANDLE_EXT, /**< external handler */ 54 RTE_INTR_HANDLE_VDEV, /**< virtual device */ 55 RTE_INTR_HANDLE_DEV_EVENT, /**< device event handle */ 56 RTE_INTR_HANDLE_VFIO_REQ, /**< VFIO request handle */ 57 RTE_INTR_HANDLE_MAX /**< count of elements */ 58 }; 59 60 /** Function to be registered for the specific interrupt */ 61 typedef void (*rte_intr_callback_fn)(void *cb_arg); 62 63 /** 64 * Function to call after a callback is unregistered. 65 * Can be used to close fd and free cb_arg. 66 */ 67 typedef void (*rte_intr_unregister_callback_fn)(struct rte_intr_handle *intr_handle, 68 void *cb_arg); 69 70 /** 71 * It registers the callback for the specific interrupt. Multiple 72 * callbacks can be registered at the same time. 73 * @param intr_handle 74 * Pointer to the interrupt handle. 75 * @param cb 76 * callback address. 77 * @param cb_arg 78 * address of parameter for callback. 79 * 80 * @return 81 * - On success, zero. 82 * - On failure, a negative value. 83 */ 84 int rte_intr_callback_register(const struct rte_intr_handle *intr_handle, 85 rte_intr_callback_fn cb, void *cb_arg); 86 87 /** 88 * It unregisters the callback according to the specified interrupt handle. 89 * 90 * @param intr_handle 91 * pointer to the interrupt handle. 92 * @param cb 93 * callback address. 94 * @param cb_arg 95 * address of parameter for callback, (void *)-1 means to remove all 96 * registered which has the same callback address. 97 * 98 * @return 99 * - On success, return the number of callback entities removed. 100 * - On failure, a negative value. 101 */ 102 int rte_intr_callback_unregister(const struct rte_intr_handle *intr_handle, 103 rte_intr_callback_fn cb, void *cb_arg); 104 105 /** 106 * Unregister the callback according to the specified interrupt handle, 107 * after it's no longer active. Fail if source is not active. 108 * 109 * @param intr_handle 110 * pointer to the interrupt handle. 111 * @param cb_fn 112 * callback address. 113 * @param cb_arg 114 * address of parameter for callback, (void *)-1 means to remove all 115 * registered which has the same callback address. 116 * @param ucb_fn 117 * callback to call before cb is unregistered (optional). 118 * can be used to close fd and free cb_arg. 119 * 120 * @return 121 * - On success, return the number of callback entities marked for remove. 122 * - On failure, a negative value. 123 */ 124 int 125 rte_intr_callback_unregister_pending(const struct rte_intr_handle *intr_handle, 126 rte_intr_callback_fn cb_fn, void *cb_arg, 127 rte_intr_unregister_callback_fn ucb_fn); 128 129 /** 130 * @warning 131 * @b EXPERIMENTAL: this API may change without prior notice 132 * 133 * Loop until rte_intr_callback_unregister() succeeds. 134 * After a call to this function, 135 * the callback provided by the specified interrupt handle is unregistered. 136 * 137 * @param intr_handle 138 * pointer to the interrupt handle. 139 * @param cb 140 * callback address. 141 * @param cb_arg 142 * address of parameter for callback, (void *)-1 means to remove all 143 * registered which has the same callback address. 144 * 145 * @return 146 * - On success, return the number of callback entities removed. 147 * - On failure, a negative value. 148 */ 149 __rte_experimental 150 int 151 rte_intr_callback_unregister_sync(const struct rte_intr_handle *intr_handle, 152 rte_intr_callback_fn cb, void *cb_arg); 153 154 /** 155 * It enables the interrupt for the specified handle. 156 * 157 * @param intr_handle 158 * pointer to the interrupt handle. 159 * 160 * @return 161 * - On success, zero. 162 * - On failure, a negative value. 163 */ 164 int rte_intr_enable(const struct rte_intr_handle *intr_handle); 165 166 /** 167 * It disables the interrupt for the specified handle. 168 * 169 * @param intr_handle 170 * pointer to the interrupt handle. 171 * 172 * @return 173 * - On success, zero. 174 * - On failure, a negative value. 175 */ 176 int rte_intr_disable(const struct rte_intr_handle *intr_handle); 177 178 /** 179 * It acknowledges an interrupt raised for the specified handle. 180 * 181 * This function should be called at the end of each interrupt handler either 182 * from application or driver, so that currently raised interrupt is acked and 183 * further new interrupts are raised. 184 * 185 * @param intr_handle 186 * pointer to the interrupt handle. 187 * 188 * @return 189 * - On success, zero. 190 * - On failure, a negative value. 191 */ 192 int rte_intr_ack(const struct rte_intr_handle *intr_handle); 193 194 /** 195 * Check if currently executing in interrupt context 196 * 197 * @return 198 * - non zero in case of interrupt context 199 * - zero in case of process context 200 */ 201 int rte_thread_is_intr(void); 202 203 /** 204 * @warning 205 * @b EXPERIMENTAL: this API may change without prior notice 206 * 207 * It allocates memory for interrupt instance. API takes flag as an argument 208 * which define from where memory should be allocated i.e. using DPDK memory 209 * management library APIs or normal heap allocation. 210 * Default memory allocation for event fds and event list array is done which 211 * can be realloced later based on size of MSIX interrupts supported by a PCI 212 * device. 213 * 214 * This function should be called from application or driver, before calling 215 * any of the interrupt APIs. 216 * 217 * @param flags 218 * See RTE_INTR_INSTANCE_F_* flags definitions. 219 * 220 * @return 221 * - On success, address of interrupt handle. 222 * - On failure, NULL. 223 */ 224 __rte_experimental 225 struct rte_intr_handle * 226 rte_intr_instance_alloc(uint32_t flags); 227 228 /** 229 * @warning 230 * @b EXPERIMENTAL: this API may change without prior notice 231 * 232 * Free the memory allocated for interrupt handle resources. 233 * 234 * @param intr_handle 235 * Interrupt handle allocated with rte_intr_instance_alloc(). 236 * If intr_handle is NULL, no operation is performed. 237 * 238 */ 239 __rte_experimental 240 void 241 rte_intr_instance_free(struct rte_intr_handle *intr_handle); 242 243 /** 244 * @warning 245 * @b EXPERIMENTAL: this API may change without prior notice 246 * 247 * Set the fd field of interrupt handle with user provided 248 * file descriptor. 249 * 250 * @param intr_handle 251 * pointer to the interrupt handle. 252 * @param fd 253 * file descriptor value provided by user. 254 * 255 * @return 256 * - On success, zero. 257 * - On failure, a negative value and rte_errno is set. 258 */ 259 __rte_experimental 260 int 261 rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd); 262 263 /** 264 * @warning 265 * @b EXPERIMENTAL: this API may change without prior notice 266 * 267 * Returns the fd field of the given interrupt handle instance. 268 * 269 * @param intr_handle 270 * pointer to the interrupt handle. 271 * 272 * @return 273 * - On success, fd field. 274 * - On failure, a negative value. 275 */ 276 __rte_experimental 277 int 278 rte_intr_fd_get(const struct rte_intr_handle *intr_handle); 279 280 /** 281 * @warning 282 * @b EXPERIMENTAL: this API may change without prior notice 283 * 284 * Set the type field of interrupt handle with user provided 285 * interrupt type. 286 * 287 * @param intr_handle 288 * pointer to the interrupt handle. 289 * @param type 290 * interrupt type 291 * 292 * @return 293 * - On success, zero. 294 * - On failure, a negative value and rte_errno is set. 295 */ 296 __rte_experimental 297 int 298 rte_intr_type_set(struct rte_intr_handle *intr_handle, 299 enum rte_intr_handle_type type); 300 301 /** 302 * @warning 303 * @b EXPERIMENTAL: this API may change without prior notice 304 * 305 * Returns the type field of the given interrupt handle instance. 306 * 307 * @param intr_handle 308 * pointer to the interrupt handle. 309 * 310 * @return 311 * - On success, interrupt type 312 * - On failure, RTE_INTR_HANDLE_UNKNOWN. 313 */ 314 __rte_experimental 315 enum rte_intr_handle_type 316 rte_intr_type_get(const struct rte_intr_handle *intr_handle); 317 318 /** 319 * @internal 320 * The function returns the per thread epoll instance. 321 * 322 * @return 323 * epfd the epoll instance referred to. 324 */ 325 __rte_internal 326 int 327 rte_intr_tls_epfd(void); 328 329 /** 330 * @internal 331 * @param intr_handle 332 * Pointer to the interrupt handle. 333 * @param epfd 334 * Epoll instance fd which the intr vector associated to. 335 * @param op 336 * The operation be performed for the vector. 337 * Operation type of {ADD, DEL}. 338 * @param vec 339 * RX intr vector number added to the epoll instance wait list. 340 * @param data 341 * User raw data. 342 * @return 343 * - On success, zero. 344 * - On failure, a negative value. 345 */ 346 __rte_internal 347 int 348 rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, 349 int epfd, int op, unsigned int vec, void *data); 350 351 /** 352 * @internal 353 * It deletes registered eventfds. 354 * 355 * @param intr_handle 356 * Pointer to the interrupt handle. 357 */ 358 __rte_internal 359 void 360 rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle); 361 362 /** 363 * @internal 364 * It enables the packet I/O interrupt event if it's necessary. 365 * It creates event fd for each interrupt vector when MSIX is used, 366 * otherwise it multiplexes a single event fd. 367 * 368 * @param intr_handle 369 * Pointer to the interrupt handle. 370 * @param nb_efd 371 * Number of interrupt vector trying to enable. 372 * The value 0 is not allowed. 373 * @return 374 * - On success, zero. 375 * - On failure, a negative value. 376 */ 377 __rte_internal 378 int 379 rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); 380 381 /** 382 * @internal 383 * It disables the packet I/O interrupt event. 384 * It deletes registered eventfds and closes the open fds. 385 * 386 * @param intr_handle 387 * Pointer to the interrupt handle. 388 */ 389 __rte_internal 390 void 391 rte_intr_efd_disable(struct rte_intr_handle *intr_handle); 392 393 /** 394 * @internal 395 * The packet I/O interrupt on datapath is enabled or not. 396 * 397 * @param intr_handle 398 * Pointer to the interrupt handle. 399 */ 400 __rte_internal 401 int 402 rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); 403 404 /** 405 * @internal 406 * The interrupt handle instance allows other causes or not. 407 * Other causes stand for any none packet I/O interrupts. 408 * 409 * @param intr_handle 410 * Pointer to the interrupt handle. 411 */ 412 __rte_internal 413 int 414 rte_intr_allow_others(struct rte_intr_handle *intr_handle); 415 416 /** 417 * @internal 418 * The multiple interrupt vector capability of interrupt handle instance. 419 * It returns zero if no multiple interrupt vector support. 420 * 421 * @param intr_handle 422 * Pointer to the interrupt handle. 423 */ 424 __rte_internal 425 int 426 rte_intr_cap_multiple(struct rte_intr_handle *intr_handle); 427 428 /** 429 * @internal 430 * Creates a clone of src by allocating a new handle and copying src content. 431 * 432 * @param src 433 * Source interrupt handle to be cloned. 434 * 435 * @return 436 * - On success, address of interrupt handle. 437 * - On failure, NULL. 438 */ 439 __rte_internal 440 struct rte_intr_handle * 441 rte_intr_instance_dup(const struct rte_intr_handle *src); 442 443 /** 444 * @internal 445 * Set the device fd field of interrupt handle with user 446 * provided dev fd. Device fd corresponds to VFIO device fd or UIO config fd. 447 * 448 * @param intr_handle 449 * pointer to the interrupt handle. 450 * @param fd 451 * interrupt type 452 * 453 * @return 454 * - On success, zero. 455 * - On failure, a negative value and rte_errno is set. 456 */ 457 __rte_internal 458 int 459 rte_intr_dev_fd_set(struct rte_intr_handle *intr_handle, int fd); 460 461 /** 462 * @internal 463 * Returns the device fd field of the given interrupt handle instance. 464 * 465 * @param intr_handle 466 * pointer to the interrupt handle. 467 * 468 * @return 469 * - On success, dev fd. 470 * - On failure, a negative value and rte_errno is set. 471 */ 472 __rte_internal 473 int 474 rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle); 475 476 /** 477 * @internal 478 * Set the max intr field of interrupt handle with user 479 * provided max intr value. 480 * 481 * @param intr_handle 482 * pointer to the interrupt handle. 483 * @param max_intr 484 * interrupt type 485 * 486 * @return 487 * - On success, zero. 488 * - On failure, a negative value and rte_errno is set. 489 */ 490 __rte_internal 491 int 492 rte_intr_max_intr_set(struct rte_intr_handle *intr_handle, int max_intr); 493 494 /** 495 * @internal 496 * Returns the max intr field of the given interrupt handle instance. 497 * 498 * @param intr_handle 499 * pointer to the interrupt handle. 500 * 501 * @return 502 * - On success, max intr. 503 * - On failure, a negative value and rte_errno is set. 504 */ 505 __rte_internal 506 int 507 rte_intr_max_intr_get(const struct rte_intr_handle *intr_handle); 508 509 /** 510 * @internal 511 * Set the number of event fd field of interrupt handle 512 * with user provided available event file descriptor value. 513 * 514 * @param intr_handle 515 * pointer to the interrupt handle. 516 * @param nb_efd 517 * Available event fd 518 * 519 * @return 520 * - On success, zero. 521 * - On failure, a negative value and rte_errno is set. 522 */ 523 __rte_internal 524 int 525 rte_intr_nb_efd_set(struct rte_intr_handle *intr_handle, int nb_efd); 526 527 /** 528 * @internal 529 * Returns the number of available event fd field of the given interrupt handle 530 * instance. 531 * 532 * @param intr_handle 533 * pointer to the interrupt handle. 534 * 535 * @return 536 * - On success, nb_efd 537 * - On failure, a negative value and rte_errno is set. 538 */ 539 __rte_internal 540 int 541 rte_intr_nb_efd_get(const struct rte_intr_handle *intr_handle); 542 543 /** 544 * @internal 545 * Returns the number of interrupt vector field of the given interrupt handle 546 * instance. This field is to configured on device probe time, and based on 547 * this value efds and elist arrays are dynamically allocated. By default 548 * this value is set to RTE_MAX_RXTX_INTR_VEC_ID. 549 * For eg. in case of PCI device, its msix size is queried and efds/elist 550 * arrays are allocated accordingly. 551 * 552 * @param intr_handle 553 * pointer to the interrupt handle. 554 * 555 * @return 556 * - On success, nb_intr 557 * - On failure, a negative value and rte_errno is set. 558 */ 559 __rte_internal 560 int 561 rte_intr_nb_intr_get(const struct rte_intr_handle *intr_handle); 562 563 /** 564 * @internal 565 * Set the event fd counter size field of interrupt handle 566 * with user provided efd counter size. 567 * 568 * @param intr_handle 569 * pointer to the interrupt handle. 570 * @param efd_counter_size 571 * size of efd counter. 572 * 573 * @return 574 * - On success, zero. 575 * - On failure, a negative value and rte_errno is set. 576 */ 577 __rte_internal 578 int 579 rte_intr_efd_counter_size_set(struct rte_intr_handle *intr_handle, 580 uint8_t efd_counter_size); 581 582 /** 583 * @internal 584 * Returns the event fd counter size field of the given interrupt handle 585 * instance. 586 * 587 * @param intr_handle 588 * pointer to the interrupt handle. 589 * 590 * @return 591 * - On success, efd_counter_size 592 * - On failure, a negative value and rte_errno is set. 593 */ 594 __rte_internal 595 int 596 rte_intr_efd_counter_size_get(const struct rte_intr_handle *intr_handle); 597 598 /** 599 * @internal 600 * Set the event fd array index with the given fd. 601 * 602 * @param intr_handle 603 * pointer to the interrupt handle. 604 * @param index 605 * efds array index to be set 606 * @param fd 607 * event fd 608 * 609 * @return 610 * - On success, zero. 611 * - On failure, a negative value and rte_errno is set. 612 */ 613 __rte_internal 614 int 615 rte_intr_efds_index_set(struct rte_intr_handle *intr_handle, int index, int fd); 616 617 /** 618 * @internal 619 * Returns the fd value of event fds array at a given index. 620 * 621 * @param intr_handle 622 * pointer to the interrupt handle. 623 * @param index 624 * efds array index to be returned 625 * 626 * @return 627 * - On success, fd 628 * - On failure, a negative value and rte_errno is set. 629 */ 630 __rte_internal 631 int 632 rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle, int index); 633 634 /** 635 * @internal 636 * Set the epoll event object array index with the given 637 * elist instance. 638 * 639 * @param intr_handle 640 * pointer to the interrupt handle. 641 * @param index 642 * elist array index to be set 643 * @param elist 644 * epoll event instance of struct rte_epoll_event 645 * 646 * @return 647 * - On success, zero. 648 * - On failure, a negative value and rte_errno is set. 649 */ 650 __rte_internal 651 int 652 rte_intr_elist_index_set(struct rte_intr_handle *intr_handle, int index, 653 struct rte_epoll_event elist); 654 655 /** 656 * @internal 657 * Returns the address of epoll event instance from elist array at a given 658 * index. 659 * 660 * @param intr_handle 661 * pointer to the interrupt handle. 662 * @param index 663 * elist array index to be returned 664 * 665 * @return 666 * - On success, elist 667 * - On failure, a negative value and rte_errno is set. 668 */ 669 __rte_internal 670 struct rte_epoll_event * 671 rte_intr_elist_index_get(struct rte_intr_handle *intr_handle, int index); 672 673 /** 674 * @internal 675 * Allocates the memory of interrupt vector list array, with size defining the 676 * number of elements required in the array. 677 * 678 * @param intr_handle 679 * pointer to the interrupt handle. 680 * @param name 681 * Name assigned to the allocation, or NULL. 682 * @param size 683 * Number of element required in the array. 684 * 685 * @return 686 * - On success, zero 687 * - On failure, a negative value and rte_errno is set. 688 */ 689 __rte_internal 690 int 691 rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle, const char *name, 692 int size); 693 694 /** 695 * @internal 696 * Sets the vector value at given index of interrupt vector list field of given 697 * interrupt handle. 698 * 699 * @param intr_handle 700 * pointer to the interrupt handle. 701 * @param index 702 * intr_vec array index to be set 703 * @param vec 704 * Interrupt vector value. 705 * 706 * @return 707 * - On success, zero 708 * - On failure, a negative value and rte_errno is set. 709 */ 710 __rte_internal 711 int 712 rte_intr_vec_list_index_set(struct rte_intr_handle *intr_handle, int index, 713 int vec); 714 715 /** 716 * @internal 717 * Returns the vector value at the given index of interrupt vector list array. 718 * 719 * @param intr_handle 720 * pointer to the interrupt handle. 721 * @param index 722 * intr_vec array index to be returned 723 * 724 * @return 725 * - On success, interrupt vector 726 * - On failure, a negative value and rte_errno is set. 727 */ 728 __rte_internal 729 int 730 rte_intr_vec_list_index_get(const struct rte_intr_handle *intr_handle, 731 int index); 732 733 /** 734 * @internal 735 * Frees the memory allocated for interrupt vector list array. 736 * 737 * @param intr_handle 738 * pointer to the interrupt handle. 739 * 740 * @return 741 * - On success, zero 742 * - On failure, a negative value and rte_errno is set. 743 */ 744 __rte_internal 745 void 746 rte_intr_vec_list_free(struct rte_intr_handle *intr_handle); 747 748 /** 749 * @internal 750 * Reallocates the size efds and elist array based on size provided by user. 751 * By default efds and elist array are allocated with default size 752 * RTE_MAX_RXTX_INTR_VEC_ID on interrupt handle array creation. Later on device 753 * probe, device may have capability of more interrupts than 754 * RTE_MAX_RXTX_INTR_VEC_ID. Using this API, PMDs can reallocate the arrays as 755 * per the max interrupts capability of device. 756 * 757 * @param intr_handle 758 * pointer to the interrupt handle. 759 * @param size 760 * efds and elist array size. 761 * 762 * @return 763 * - On success, zero 764 * - On failure, a negative value and rte_errno is set. 765 */ 766 __rte_internal 767 int 768 rte_intr_event_list_update(struct rte_intr_handle *intr_handle, int size); 769 770 /** 771 * @internal 772 * Returns the Windows handle of the given interrupt instance. 773 * 774 * @param intr_handle 775 * pointer to the interrupt handle. 776 * 777 * @return 778 * - On success, Windows handle. 779 * - On failure, NULL. 780 */ 781 __rte_internal 782 void * 783 rte_intr_instance_windows_handle_get(struct rte_intr_handle *intr_handle); 784 785 /** 786 * @internal 787 * Set the Windows handle for the given interrupt instance. 788 * 789 * @param intr_handle 790 * pointer to the interrupt handle. 791 * @param windows_handle 792 * Windows handle to be set. 793 * 794 * @return 795 * - On success, zero 796 * - On failure, a negative value and rte_errno is set. 797 */ 798 __rte_internal 799 int 800 rte_intr_instance_windows_handle_set(struct rte_intr_handle *intr_handle, 801 void *windows_handle); 802 803 #ifdef __cplusplus 804 } 805 #endif 806 807 #endif 808