The patch adds 'rte_intr_rx_ctl' to add or delete interrupt vector events 
monitor on specified epoll instance.

Signed-off-by: Cunming Liang <cunming.liang at intel.com>
---
v7 changes
 - rename rte_intr_rx_set to rte_intr_rx_ctl.
 - rte_intr_rx_ctl uses rte_epoll_ctl to register epoll event instance.
 - the intr rx event instance includes a intr process callback.

v6 changes
 - split rte_intr_wait_rx_pkt into two function, wait and set.
 - rewrite rte_intr_rx_wait/rte_intr_rx_set to remove queue visibility on eal.
 - rte_intr_rx_wait to support multiplexing.
 - allow epfd as input to support flexible event fd combination.

 lib/librte_eal/linuxapp/eal/eal_interrupts.c       | 95 ++++++++++++++++++++++
 .../linuxapp/eal/include/exec-env/rte_interrupts.h | 23 ++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |  1 +
 3 files changed, 119 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c 
b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index b641745..1090d7b 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -862,6 +862,35 @@ rte_eal_intr_init(void)
 }

 static void
+eal_intr_proc_rxtx_intr(int fd, struct rte_intr_handle *intr_handle)
+{
+       union rte_intr_read_buffer buf;
+       int bytes_read = 1;
+
+       if (intr_handle->type != RTE_INTR_HANDLE_VFIO_MSIX) {
+               RTE_LOG(ERR, EAL, "intr type should be VFIO_MSIX\n");
+               return;
+       }
+
+#ifdef VFIO_PRESENT
+       bytes_read = sizeof(buf.vfio_intr_count);
+#endif
+
+       /**
+        * read out to clear the ready-to-be-read flag
+        * for epoll_wait.
+        */
+       bytes_read = read(fd, &buf, bytes_read);
+       if (bytes_read < 0)
+               RTE_LOG(ERR, EAL, "Error reading from file "
+                       "descriptor %d: %s\n", fd,
+                       strerror(errno));
+       else if (bytes_read == 0)
+               RTE_LOG(ERR, EAL, "Read nothing from file "
+                       "descriptor %d\n", fd);
+}
+
+static void
 eal_epoll_process_event(struct epoll_event *evs, int n,
                        struct rte_epoll_event *events)
 {
@@ -956,3 +985,69 @@ rte_epoll_ctl(int epfd, int op, int fd,

        return 0;
 }
+
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
+               int op, unsigned int vec, void *data, int socket)
+{
+       struct rte_epoll_event *rev;
+       int epfd_op;
+       int rc = 0;
+
+       if (!intr_handle || vec >= RTE_MAX_RXTX_INTR_VEC_ID ||
+           !intr_handle->vec_en) {
+               RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
+               return -1;
+       }
+
+       if (socket == SOCKET_ID_ANY)
+               socket = rte_socket_id();
+
+       switch (op) {
+       case RTE_INTR_EVENT_ADD:
+               epfd_op = EPOLL_CTL_ADD;
+               if (intr_handle->eptrs[vec] != NULL) {
+                       RTE_LOG(ERR, EAL, "Event already been added.\n");
+                       return -1;
+               }
+
+               /* new event */
+               rev = rte_zmalloc_socket("eptrs", sizeof(*rev),
+                                        RTE_CACHE_LINE_SIZE, socket);
+               if (rev == NULL) {
+                       RTE_LOG(ERR, EAL, "event obj alloc fail\n");
+                       return -1;
+               }
+
+               /* attach to intr vector fd */
+               rev->fd     = intr_handle->efds[vec];
+               rev->event  = EPOLLIN | EPOLLPRI | EPOLLET;
+               rev->data   = data;
+               rev->cb_fun = (rte_intr_event_cb_t)eal_intr_proc_rxtx_intr;
+               rev->cb_arg = (void *)intr_handle;
+
+               rc = rte_epoll_ctl(epfd, epfd_op, rev->fd, rev);
+               if (!rc)
+                       intr_handle->eptrs[vec] = rev;
+               else
+                       rte_free(rev);
+
+               break;
+       case RTE_INTR_EVENT_DEL:
+               epfd_op = EPOLL_CTL_DEL;
+               if (intr_handle->eptrs[vec] != NULL) {
+                       rev = intr_handle->eptrs[vec];
+                       rc = rte_epoll_ctl(epfd, epfd_op, rev->fd, rev);
+                       if (!rc) {
+                               rte_free(rev);
+                               intr_handle->eptrs[vec] = NULL;
+                       }
+               }
+               break;
+       default:
+               RTE_LOG(ERR, EAL, "event op type mismatch\n");
+               rc = -1;
+       }
+
+       return rc;
+}
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 af405cf..3d9f6d7 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
@@ -133,4 +133,27 @@ rte_epoll_ctl(int epfd, int op, int fd,
 int
 rte_intr_tls_epfd(void);

+/**
+ * @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.
+ * @param socket
+ *   Specifying the socket id.
+ * @return
+ *   - On success, zero.
+ *   - On failure, a negative value.
+ */
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+               int epfd, int op, unsigned int vec,
+               void *data, int socket);
+
 #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 840002e..65b5ed2 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -63,6 +63,7 @@ DPDK_2.0 {
        rte_intr_callback_unregister;
        rte_intr_disable;
        rte_intr_enable;
+       rte_intr_rx_ctl;
        rte_intr_tls_epfd;
        rte_log;
        rte_log_add_in_history;
-- 
1.8.1.4

Reply via email to