From b9e0662a931dfc1d2e29492de666e3ac3804868f Mon Sep 17 00:00:00 2001 From: Cunming Liang Date: Mon, 20 Jul 2015 11:02:22 +0800 Subject: [PATCH] eal/linux: add interrupt API for drivers The patch exposes intr event fd create and release for PMD. The device driver can assign the number of event associated with interrupt vector. It also provides misc functions to check 1) allows other slowpath intr(e.g. lsc); 2) intr event on fastpath is enabled or not. Signed-off-by: Cunming Liang --- lib/librte_eal/bsdapp/eal/eal_interrupts.c | 29 ++++++ .../eal/include/exec-env/rte_interrupts.h | 43 ++++++++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 + lib/librte_eal/linuxapp/eal/eal_interrupts.c | 97 +++++++++++++++++++ .../eal/include/exec-env/rte_interrupts.h | 45 +++++++++ .../linuxapp/eal/rte_eal_version.map | 4 + 6 files changed, 222 insertions(+) diff --git a/lib/librte_eal/bsdapp/eal/eal_interrupts.c b/lib/librte_eal/bsdapp/eal/eal_interrupts.c index d5ae6829e0..51a13fa264 100644 --- a/lib/librte_eal/bsdapp/eal/eal_interrupts.c +++ b/lib/librte_eal/bsdapp/eal/eal_interrupts.c @@ -81,3 +81,32 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, return -ENOTSUP; } + +int +rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) +{ + RTE_SET_USED(intr_handle); + RTE_SET_USED(nb_efd); + + return 0; +} + +void +rte_intr_efd_disable(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); +} + +int +rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); + return 0; +} + +int +rte_intr_allow_others(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); + return 1; +} diff --git a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h index 67cb0c9a2d..bffa902474 100644 --- a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h +++ b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h @@ -77,4 +77,47 @@ int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data); +/** + * It enables the fastpath event fds if it's necessary. + * It creates event fds when multi-vectors allowed, + * otherwise it multiplexes the single event fds. + * + * @param intr_handle + * Pointer to the interrupt handle. + * @param nb_vec + * Number of interrupt vector trying to enable. + * @return + * - On success, zero. + * - On failure, a negative value. + */ +int +rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); + +/** + * It disable the fastpath event fds. + * It deletes registered eventfds and closes the open fds. + * + * @param intr_handle + * Pointer to the interrupt handle. + */ +void +rte_intr_efd_disable(struct rte_intr_handle *intr_handle); + +/** + * The fastpath interrupt is enabled or not. + * + * @param intr_handle + * Pointer to the interrupt handle. + */ +int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); + +/** + * The interrupt handle instance allows other cause or not. + * Other cause stands for none fastpath interrupt. + * + * @param intr_handle + * Pointer to the interrupt handle. + */ +int rte_intr_allow_others(struct rte_intr_handle *intr_handle); + #endif /* _RTE_BSDAPP_INTERRUPTS_H_ */ diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index 412ba1e42a..2758848e2f 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -118,6 +118,10 @@ DPDK_2.1 { rte_eal_pci_detach; rte_eal_pci_read_config; rte_eal_pci_write_config; + rte_intr_allow_others; + rte_intr_dp_is_en; + rte_intr_efd_disable; + rte_intr_efd_enable; rte_intr_rx_ctl; rte_memzone_free; diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c index e919fb0705..3f87875aa8 100644 --- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c +++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,7 @@ #include "eal_vfio.h" #define EAL_INTR_EPOLL_WAIT_FOREVER (-1) +#define NB_OTHER_INTR 1 static RTE_DEFINE_PER_LCORE(int, _epfd) = -1; /**< epoll fd per thread */ @@ -1124,6 +1126,73 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, return rc; } + +int +rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) +{ + uint32_t i; + int fd; + uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); + + if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) { + for (i = 0; i < n; i++) { + fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + if (fd < 0) { + RTE_LOG(ERR, EAL, + "can't setup eventfd, error %i (%s)\n", + errno, strerror(errno)); + return -1; + } + intr_handle->efds[i] = fd; + } + intr_handle->nb_efd = n; + intr_handle->max_intr = NB_OTHER_INTR + n; + } else { + intr_handle->efds[0] = intr_handle->fd; + intr_handle->nb_efd = RTE_MIN(nb_efd, 1U); + intr_handle->max_intr = NB_OTHER_INTR; + } + + return 0; +} + +void +rte_intr_efd_disable(struct rte_intr_handle *intr_handle) +{ + uint32_t i; + struct rte_epoll_event *rev; + + for (i = 0; i < intr_handle->nb_efd; i++) { + rev = &intr_handle->elist[i]; + if (rev->status == RTE_EPOLL_INVALID) + continue; + if (rte_epoll_ctl(rev->epfd, EPOLL_CTL_DEL, rev->fd, rev)) { + /* force free if the entry valid */ + eal_epoll_data_safe_free(rev); + rev->status = RTE_EPOLL_INVALID; + } + } + + if (intr_handle->max_intr > intr_handle->nb_efd) { + for (i = 0; i < intr_handle->nb_efd; i++) + close(intr_handle->efds[i]); + } + intr_handle->nb_efd = 0; + intr_handle->max_intr = 0; +} + +int +rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) +{ + return !(!intr_handle->nb_efd); +} + +int +rte_intr_allow_others(struct rte_intr_handle *intr_handle) +{ + return !!(intr_handle->max_intr - intr_handle->nb_efd); +} + #else int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, @@ -1136,4 +1205,32 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, RTE_SET_USED(data); return -ENOTSUP; } + +int +rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) +{ + RTE_SET_USED(intr_handle); + RTE_SET_USED(nb_efd); + return 0; +} + +void +rte_intr_efd_disable(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); +} + +int +rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); + return 0; +} + +int +rte_intr_allow_others(struct rte_intr_handle *intr_handle) +{ + RTE_SET_USED(intr_handle); + return 1; +} #endif diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h index acf4be9d8b..b05f4c87e7 100644 --- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h +++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h @@ -168,4 +168,49 @@ int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data); +/** + * 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_vec + * Number of interrupt vector trying to enable. + * @return + * - On success, zero. + * - On failure, a negative value. + */ +int +rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); + +/** + * 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. + */ +void +rte_intr_efd_disable(struct rte_intr_handle *intr_handle); + +/** + * The packet I/O interrupt on datapath is enabled or not. + * + * @param intr_handle + * Pointer to the interrupt handle. + */ +int +rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); + +/** + * 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. + */ +int +rte_intr_allow_others(struct rte_intr_handle *intr_handle); + #endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 7e20d7a06d..59b1717940 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -120,6 +120,10 @@ DPDK_2.1 { rte_eal_pci_write_config; rte_epoll_ctl; rte_epoll_wait; + rte_intr_allow_others; + rte_intr_dp_is_en; + rte_intr_efd_disable; + rte_intr_efd_enable; rte_intr_rx_ctl; rte_intr_tls_epfd; rte_memzone_free; -- 2.20.1