/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2014 Intel Corporation */ #ifndef _RTE_INTERRUPTS_H_ #define _RTE_INTERRUPTS_H_ #include #include #include #include #include /** * @file * * The RTE interrupt interface provides functions to register/unregister * callbacks for a specific interrupt. */ #ifdef __cplusplus extern "C" { #endif /** Interrupt handle */ struct rte_intr_handle; /** Interrupt instance allocation flags * @see rte_intr_instance_alloc */ /** Interrupt instance will not be shared between primary and secondary processes. */ #define RTE_INTR_INSTANCE_F_PRIVATE UINT32_C(0) /** Interrupt instance will be shared between primary and secondary processes. */ #define RTE_INTR_INSTANCE_F_SHARED RTE_BIT32(0) #define RTE_MAX_RXTX_INTR_VEC_ID 512 #define RTE_INTR_VEC_ZERO_OFFSET 0 #define RTE_INTR_VEC_RXTX_OFFSET 1 /** * The interrupt source type, e.g. UIO, VFIO, ALARM etc. */ enum rte_intr_handle_type { RTE_INTR_HANDLE_UNKNOWN = 0, /**< generic unknown handle */ RTE_INTR_HANDLE_UIO, /**< uio device handle */ RTE_INTR_HANDLE_UIO_INTX, /**< uio generic handle */ RTE_INTR_HANDLE_VFIO_LEGACY, /**< vfio device handle (legacy) */ RTE_INTR_HANDLE_VFIO_MSI, /**< vfio device handle (MSI) */ RTE_INTR_HANDLE_VFIO_MSIX, /**< vfio device handle (MSIX) */ RTE_INTR_HANDLE_ALARM, /**< alarm handle */ RTE_INTR_HANDLE_EXT, /**< external handler */ RTE_INTR_HANDLE_VDEV, /**< virtual device */ RTE_INTR_HANDLE_DEV_EVENT, /**< device event handle */ RTE_INTR_HANDLE_VFIO_REQ, /**< VFIO request handle */ RTE_INTR_HANDLE_MAX /**< count of elements */ }; /** Function to be registered for the specific interrupt */ typedef void (*rte_intr_callback_fn)(void *cb_arg); /** * Function to call after a callback is unregistered. * Can be used to close fd and free cb_arg. */ typedef void (*rte_intr_unregister_callback_fn)(struct rte_intr_handle *intr_handle, void *cb_arg); /** * It registers the callback for the specific interrupt. Multiple * callbacks can be registered at the same time. * @param intr_handle * Pointer to the interrupt handle. * @param cb * callback address. * @param cb_arg * address of parameter for callback. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_callback_register(const struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg); /** * It unregisters the callback according to the specified interrupt handle. * * @param intr_handle * pointer to the interrupt handle. * @param cb * callback address. * @param cb_arg * address of parameter for callback, (void *)-1 means to remove all * registered which has the same callback address. * * @return * - On success, return the number of callback entities removed. * - On failure, a negative value. */ int rte_intr_callback_unregister(const struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg); /** * Unregister the callback according to the specified interrupt handle, * after it's no longer active. Fail if source is not active. * * @param intr_handle * pointer to the interrupt handle. * @param cb_fn * callback address. * @param cb_arg * address of parameter for callback, (void *)-1 means to remove all * registered which has the same callback address. * @param ucb_fn * callback to call before cb is unregistered (optional). * can be used to close fd and free cb_arg. * * @return * - On success, return the number of callback entities marked for remove. * - On failure, a negative value. */ __rte_experimental int rte_intr_callback_unregister_pending(const struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb_fn, void *cb_arg, rte_intr_unregister_callback_fn ucb_fn); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * Loop until rte_intr_callback_unregister() succeeds. * After a call to this function, * the callback provided by the specified interrupt handle is unregistered. * * @param intr_handle * pointer to the interrupt handle. * @param cb * callback address. * @param cb_arg * address of parameter for callback, (void *)-1 means to remove all * registered which has the same callback address. * * @return * - On success, return the number of callback entities removed. * - On failure, a negative value. */ __rte_experimental int rte_intr_callback_unregister_sync(const struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg); /** * It enables the interrupt for the specified handle. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_enable(const struct rte_intr_handle *intr_handle); /** * It disables the interrupt for the specified handle. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_disable(const struct rte_intr_handle *intr_handle); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * It acknowledges an interrupt raised for the specified handle. * * This function should be called at the end of each interrupt handler either * from application or driver, so that currently raised interrupt is acked and * further new interrupts are raised. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero. * - On failure, a negative value. */ __rte_experimental int rte_intr_ack(const struct rte_intr_handle *intr_handle); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * Check if currently executing in interrupt context * * @return * - non zero in case of interrupt context * - zero in case of process context */ __rte_experimental int rte_thread_is_intr(void); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * It allocates memory for interrupt instance. API takes flag as an argument * which define from where memory should be allocated i.e. using DPDK memory * management library APIs or normal heap allocation. * Default memory allocation for event fds and event list array is done which * can be realloced later based on size of MSIX interrupts supported by a PCI * device. * * This function should be called from application or driver, before calling * any of the interrupt APIs. * * @param flags * See RTE_INTR_INSTANCE_F_* flags definitions. * * @return * - On success, address of interrupt handle. * - On failure, NULL. */ __rte_experimental struct rte_intr_handle * rte_intr_instance_alloc(uint32_t flags); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * This API is used to free the memory allocated for interrupt handle * resources. * * @param intr_handle * Interrupt handle address. * */ __rte_experimental void rte_intr_instance_free(struct rte_intr_handle *intr_handle); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * This API is used to set the fd field of interrupt handle with user provided * file descriptor. * * @param intr_handle * pointer to the interrupt handle. * @param fd * file descriptor value provided by user. * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_experimental int rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * Returns the fd field of the given interrupt handle instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, fd field. * - On failure, a negative value. */ __rte_experimental int rte_intr_fd_get(const struct rte_intr_handle *intr_handle); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * This API is used to set the type field of interrupt handle with user provided * interrupt type. * * @param intr_handle * pointer to the interrupt handle. * @param type * interrupt type * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_experimental int rte_intr_type_set(struct rte_intr_handle *intr_handle, enum rte_intr_handle_type type); /** * @warning * @b EXPERIMENTAL: this API may change without prior notice * * Returns the type field of the given interrupt handle instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, interrupt type * - On failure, RTE_INTR_HANDLE_UNKNOWN. */ __rte_experimental enum rte_intr_handle_type rte_intr_type_get(const struct rte_intr_handle *intr_handle); /** * @internal * The function returns the per thread epoll instance. * * @return * epfd the epoll instance referred to. */ __rte_internal int rte_intr_tls_epfd(void); /** * @internal * @param intr_handle * Pointer to the interrupt handle. * @param epfd * Epoll instance fd which the intr vector associated to. * @param op * The operation be performed for the vector. * Operation type of {ADD, DEL}. * @param vec * RX intr vector number added to the epoll instance wait list. * @param data * User raw data. * @return * - On success, zero. * - On failure, a negative value. */ __rte_internal int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data); /** * @internal * It deletes registered eventfds. * * @param intr_handle * Pointer to the interrupt handle. */ __rte_internal void rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle); /** * @internal * It enables the packet I/O interrupt event if it's necessary. * It creates event fd for each interrupt vector when MSIX is used, * otherwise it multiplexes a single event fd. * * @param intr_handle * Pointer to the interrupt handle. * @param nb_efd * Number of interrupt vector trying to enable. * The value 0 is not allowed. * @return * - On success, zero. * - On failure, a negative value. */ __rte_internal int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); /** * @internal * It disables the packet I/O interrupt event. * It deletes registered eventfds and closes the open fds. * * @param intr_handle * Pointer to the interrupt handle. */ __rte_internal void rte_intr_efd_disable(struct rte_intr_handle *intr_handle); /** * @internal * The packet I/O interrupt on datapath is enabled or not. * * @param intr_handle * Pointer to the interrupt handle. */ __rte_internal int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); /** * @internal * The interrupt handle instance allows other causes or not. * Other causes stand for any none packet I/O interrupts. * * @param intr_handle * Pointer to the interrupt handle. */ __rte_internal int rte_intr_allow_others(struct rte_intr_handle *intr_handle); /** * @internal * The multiple interrupt vector capability of interrupt handle instance. * It returns zero if no multiple interrupt vector support. * * @param intr_handle * Pointer to the interrupt handle. */ __rte_internal int rte_intr_cap_multiple(struct rte_intr_handle *intr_handle); /** * @internal * Creates a clone of src by allocating a new handle and copying src content. * * @param src * Source interrupt handle to be cloned. * * @return * - On success, address of interrupt handle. * - On failure, NULL. */ __rte_internal struct rte_intr_handle * rte_intr_instance_dup(const struct rte_intr_handle *src); /** * @internal * This API is used to set the device fd field of interrupt handle with user * provided dev fd. Device fd corresponds to VFIO device fd or UIO config fd. * * @param intr_handle * pointer to the interrupt handle. * @param fd * interrupt type * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_dev_fd_set(struct rte_intr_handle *intr_handle, int fd); /** * @internal * Returns the device fd field of the given interrupt handle instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, dev fd. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle); /** * @internal * This API is used to set the max intr field of interrupt handle with user * provided max intr value. * * @param intr_handle * pointer to the interrupt handle. * @param max_intr * interrupt type * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_max_intr_set(struct rte_intr_handle *intr_handle, int max_intr); /** * @internal * Returns the max intr field of the given interrupt handle instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, max intr. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_max_intr_get(const struct rte_intr_handle *intr_handle); /** * @internal * This API is used to set the number of event fd field of interrupt handle * with user provided available event file descriptor value. * * @param intr_handle * pointer to the interrupt handle. * @param nb_efd * Available event fd * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_nb_efd_set(struct rte_intr_handle *intr_handle, int nb_efd); /** * @internal * Returns the number of available event fd field of the given interrupt handle * instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, nb_efd * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_nb_efd_get(const struct rte_intr_handle *intr_handle); /** * @internal * Returns the number of interrupt vector field of the given interrupt handle * instance. This field is to configured on device probe time, and based on * this value efds and elist arrays are dynamically allocated. By default * this value is set to RTE_MAX_RXTX_INTR_VEC_ID. * For eg. in case of PCI device, its msix size is queried and efds/elist * arrays are allocated accordingly. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, nb_intr * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_nb_intr_get(const struct rte_intr_handle *intr_handle); /** * @internal * This API is used to set the event fd counter size field of interrupt handle * with user provided efd counter size. * * @param intr_handle * pointer to the interrupt handle. * @param efd_counter_size * size of efd counter. * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_efd_counter_size_set(struct rte_intr_handle *intr_handle, uint8_t efd_counter_size); /** * @internal * Returns the event fd counter size field of the given interrupt handle * instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, efd_counter_size * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_efd_counter_size_get(const struct rte_intr_handle *intr_handle); /** * @internal * This API is used to set the event fd array index with the given fd. * * @param intr_handle * pointer to the interrupt handle. * @param index * efds array index to be set * @param fd * event fd * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_efds_index_set(struct rte_intr_handle *intr_handle, int index, int fd); /** * @internal * Returns the fd value of event fds array at a given index. * * @param intr_handle * pointer to the interrupt handle. * @param index * efds array index to be returned * * @return * - On success, fd * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_efds_index_get(const struct rte_intr_handle *intr_handle, int index); /** * @internal * This API is used to set the epoll event object array index with the given * elist instance. * * @param intr_handle * pointer to the interrupt handle. * @param index * elist array index to be set * @param elist * epoll event instance of struct rte_epoll_event * * @return * - On success, zero. * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_elist_index_set(struct rte_intr_handle *intr_handle, int index, struct rte_epoll_event elist); /** * @internal * Returns the address of epoll event instance from elist array at a given * index. * * @param intr_handle * pointer to the interrupt handle. * @param index * elist array index to be returned * * @return * - On success, elist * - On failure, a negative value and rte_errno is set. */ __rte_internal struct rte_epoll_event * rte_intr_elist_index_get(struct rte_intr_handle *intr_handle, int index); /** * @internal * Allocates the memory of interrupt vector list array, with size defining the * number of elements required in the array. * * @param intr_handle * pointer to the interrupt handle. * @param name * Name assigned to the allocation, or NULL. * @param size * Number of element required in the array. * * @return * - On success, zero * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_vec_list_alloc(struct rte_intr_handle *intr_handle, const char *name, int size); /** * @internal * Sets the vector value at given index of interrupt vector list field of given * interrupt handle. * * @param intr_handle * pointer to the interrupt handle. * @param index * intr_vec array index to be set * @param vec * Interrupt vector value. * * @return * - On success, zero * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_vec_list_index_set(struct rte_intr_handle *intr_handle, int index, int vec); /** * @internal * Returns the vector value at the given index of interrupt vector list array. * * @param intr_handle * pointer to the interrupt handle. * @param index * intr_vec array index to be returned * * @return * - On success, interrupt vector * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_vec_list_index_get(const struct rte_intr_handle *intr_handle, int index); /** * @internal * Frees the memory allocated for interrupt vector list array. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero * - On failure, a negative value and rte_errno is set. */ __rte_internal void rte_intr_vec_list_free(struct rte_intr_handle *intr_handle); /** * @internal * Reallocates the size efds and elist array based on size provided by user. * By default efds and elist array are allocated with default size * RTE_MAX_RXTX_INTR_VEC_ID on interrupt handle array creation. Later on device * probe, device may have capability of more interrupts than * RTE_MAX_RXTX_INTR_VEC_ID. Using this API, PMDs can reallocate the arrays as * per the max interrupts capability of device. * * @param intr_handle * pointer to the interrupt handle. * @param size * efds and elist array size. * * @return * - On success, zero * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_event_list_update(struct rte_intr_handle *intr_handle, int size); /** * @internal * This API returns the Windows handle of the given interrupt instance. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, Windows handle. * - On failure, NULL. */ __rte_internal void * rte_intr_instance_windows_handle_get(struct rte_intr_handle *intr_handle); /** * @internal * This API set the Windows handle for the given interrupt instance. * * @param intr_handle * pointer to the interrupt handle. * @param windows_handle * Windows handle to be set. * * @return * - On success, zero * - On failure, a negative value and rte_errno is set. */ __rte_internal int rte_intr_instance_windows_handle_set(struct rte_intr_handle *intr_handle, void *windows_handle); #ifdef __cplusplus } #endif #endif