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