X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Flinux%2Feal%2Feal_interrupts.c;h=cb8e10709839069ca97ea8e5580db89c25d7db7e;hb=4236694f0ae466b174a73a29df4cfa94753793f0;hp=be0dd4490b65bf3545c40b90d4fa25f001fb74be;hpb=0c7ce182a7600871a45e16ff8b3a1350be5d93ae;p=dpdk.git diff --git a/lib/librte_eal/linux/eal/eal_interrupts.c b/lib/librte_eal/linux/eal/eal_interrupts.c index be0dd4490b..cb8e107098 100644 --- a/lib/librte_eal/linux/eal/eal_interrupts.c +++ b/lib/librte_eal/linux/eal/eal_interrupts.c @@ -197,6 +197,28 @@ vfio_disable_intx(const struct rte_intr_handle *intr_handle) { return 0; } +/* unmask/ack legacy (INTx) interrupts */ +static int +vfio_ack_intx(const struct rte_intr_handle *intr_handle) +{ + struct vfio_irq_set irq_set; + + /* unmask INTx */ + memset(&irq_set, 0, sizeof(irq_set)); + irq_set.argsz = sizeof(irq_set); + irq_set.count = 1; + irq_set.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK; + irq_set.index = VFIO_PCI_INTX_IRQ_INDEX; + irq_set.start = 0; + + if (ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, &irq_set)) { + RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd %d\n", + intr_handle->fd); + return -1; + } + return 0; +} + /* enable MSI interrupts */ static int vfio_enable_msi(const struct rte_intr_handle *intr_handle) { @@ -522,7 +544,7 @@ rte_intr_callback_register(const struct rte_intr_handle *intr_handle, return ret; } -int __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) @@ -693,6 +715,66 @@ rte_intr_enable(const struct rte_intr_handle *intr_handle) return 0; } +/** + * PMD generally calls this function at the end of its IRQ callback. + * Internally, it unmasks the interrupt if possible. + * + * For INTx, unmasking is required as the interrupt is auto-masked prior to + * invoking callback. + * + * For MSI/MSI-X, unmasking is typically not needed as the interrupt is not + * auto-masked. In fact, for interrupt handle types VFIO_MSIX and VFIO_MSI, + * this function is no-op. + */ +int +rte_intr_ack(const struct rte_intr_handle *intr_handle) +{ + if (intr_handle && intr_handle->type == RTE_INTR_HANDLE_VDEV) + return 0; + + if (!intr_handle || intr_handle->fd < 0 || intr_handle->uio_cfg_fd < 0) + return -1; + + switch (intr_handle->type) { + /* Both acking and enabling are same for UIO */ + case RTE_INTR_HANDLE_UIO: + if (uio_intr_enable(intr_handle)) + return -1; + break; + case RTE_INTR_HANDLE_UIO_INTX: + if (uio_intx_intr_enable(intr_handle)) + return -1; + break; + /* not used at this moment */ + case RTE_INTR_HANDLE_ALARM: + return -1; +#ifdef VFIO_PRESENT + /* VFIO MSI* is implicitly acked unlike INTx, nothing to do */ + case RTE_INTR_HANDLE_VFIO_MSIX: + case RTE_INTR_HANDLE_VFIO_MSI: + return 0; + case RTE_INTR_HANDLE_VFIO_LEGACY: + if (vfio_ack_intx(intr_handle)) + return -1; + break; +#ifdef HAVE_VFIO_DEV_REQ_INTERFACE + case RTE_INTR_HANDLE_VFIO_REQ: + return -1; +#endif +#endif + /* not used at this moment */ + case RTE_INTR_HANDLE_DEV_EVENT: + return -1; + /* unknown handle type */ + default: + RTE_LOG(ERR, EAL, "Unknown handle type of fd %d\n", + intr_handle->fd); + return -1; + } + + return 0; +} + int rte_intr_disable(const struct rte_intr_handle *intr_handle) { @@ -963,8 +1045,6 @@ eal_intr_handle_interrupts(int pfd, unsigned totalfds) static __attribute__((noreturn)) void * eal_intr_thread_main(__rte_unused void *arg) { - struct epoll_event ev; - /* host thread, never break out */ for (;;) { /* build up the epoll fd with all descriptors we are to @@ -996,8 +1076,11 @@ eal_intr_thread_main(__rte_unused void *arg) rte_spinlock_lock(&intr_lock); TAILQ_FOREACH(src, &intr_sources, next) { + struct epoll_event ev; + if (src->callbacks.tqh_first == NULL) continue; /* skip those with no callbacks */ + memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP | EPOLLHUP; ev.data.fd = src->intr_handle.fd; @@ -1405,3 +1488,8 @@ rte_intr_cap_multiple(struct rte_intr_handle *intr_handle) return 0; } + +int rte_thread_is_intr(void) +{ + return pthread_equal(intr_thread, pthread_self()); +}