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