eal/linux: add Rx interrupt control function
authorCunming Liang <cunming.liang@intel.com>
Mon, 20 Jul 2015 03:02:19 +0000 (11:02 +0800)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Mon, 27 Jul 2015 21:13:56 +0000 (23:13 +0200)
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@intel.com>
lib/librte_eal/bsdapp/eal/eal_interrupts.c
lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h
lib/librte_eal/bsdapp/eal/rte_eal_version.map
lib/librte_eal/linuxapp/eal/eal_interrupts.c
lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h
lib/librte_eal/linuxapp/eal/rte_eal_version.map

index 26a55c7..d5ae682 100644 (file)
@@ -68,3 +68,16 @@ rte_eal_intr_init(void)
 {
        return 0;
 }
+
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+               int epfd, int op, unsigned int vec, void *data)
+{
+       RTE_SET_USED(intr_handle);
+       RTE_SET_USED(epfd);
+       RTE_SET_USED(op);
+       RTE_SET_USED(vec);
+       RTE_SET_USED(data);
+
+       return -ENOTSUP;
+}
index 3dc4e00..67cb0c9 100644 (file)
@@ -57,4 +57,24 @@ struct rte_intr_handle {
 #endif
 };
 
+/**
+ * @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.
+ */
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+               int epfd, int op, unsigned int vec, void *data);
+
 #endif /* _RTE_BSDAPP_INTERRUPTS_H_ */
index 980e008..412ba1e 100644 (file)
@@ -118,6 +118,7 @@ DPDK_2.1 {
        rte_eal_pci_detach;
        rte_eal_pci_read_config;
        rte_eal_pci_write_config;
+       rte_intr_rx_ctl;
        rte_memzone_free;
 
 } DPDK_2.0;
index 55be263..ffccb0e 100644 (file)
@@ -899,6 +899,51 @@ rte_eal_intr_init(void)
        return -ret;
 }
 
+#ifdef RTE_NEXT_ABI
+static void
+eal_intr_proc_rxtx_intr(int fd, const struct rte_intr_handle *intr_handle)
+{
+       union rte_intr_read_buffer buf;
+       int bytes_read = 1;
+
+       switch (intr_handle->type) {
+       case RTE_INTR_HANDLE_UIO:
+       case RTE_INTR_HANDLE_UIO_INTX:
+               bytes_read = sizeof(buf.uio_intr_count);
+               break;
+#ifdef VFIO_PRESENT
+       case RTE_INTR_HANDLE_VFIO_MSIX:
+       case RTE_INTR_HANDLE_VFIO_MSI:
+       case RTE_INTR_HANDLE_VFIO_LEGACY:
+               bytes_read = sizeof(buf.vfio_intr_count);
+               break;
+#endif
+       default:
+               bytes_read = 1;
+               RTE_LOG(INFO, EAL, "unexpected intr type\n");
+               break;
+       }
+
+       /**
+        * read out to clear the ready-to-be-read flag
+        * for epoll_wait.
+        */
+       do {
+               bytes_read = read(fd, &buf, bytes_read);
+               if (bytes_read < 0) {
+                       if (errno == EINTR || errno == EWOULDBLOCK ||
+                           errno == EAGAIN)
+                               continue;
+                       RTE_LOG(ERR, EAL,
+                               "Error reading from fd %d: %s\n",
+                               fd, strerror(errno));
+               } else if (bytes_read == 0)
+                       RTE_LOG(ERR, EAL, "Read nothing from fd %d\n", fd);
+               return;
+       } while (1);
+}
+#endif
+
 static int
 eal_epoll_process_event(struct epoll_event *evs, unsigned int n,
                        struct rte_epoll_event *events)
@@ -1035,3 +1080,75 @@ rte_epoll_ctl(int epfd, int op, int fd,
 
        return 0;
 }
+
+#ifdef RTE_NEXT_ABI
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
+               int op, unsigned int vec, void *data)
+{
+       struct rte_epoll_event *rev;
+       struct rte_epoll_data *epdata;
+       int epfd_op;
+       int rc = 0;
+
+       if (!intr_handle || intr_handle->nb_efd == 0 ||
+           vec >= intr_handle->nb_efd) {
+               RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
+               return -EPERM;
+       }
+
+       switch (op) {
+       case RTE_INTR_EVENT_ADD:
+               epfd_op = EPOLL_CTL_ADD;
+               rev = &intr_handle->elist[vec];
+               if (rev->status != RTE_EPOLL_INVALID) {
+                       RTE_LOG(INFO, EAL, "Event already been added.\n");
+                       return -EEXIST;
+               }
+
+               /* attach to intr vector fd */
+               epdata = &rev->epdata;
+               epdata->event  = EPOLLIN | EPOLLPRI | EPOLLET;
+               epdata->data   = data;
+               epdata->cb_fun = (rte_intr_event_cb_t)eal_intr_proc_rxtx_intr;
+               epdata->cb_arg = (void *)intr_handle;
+               rc = rte_epoll_ctl(epfd, epfd_op, intr_handle->efds[vec], rev);
+               if (!rc)
+                       RTE_LOG(DEBUG, EAL,
+                               "efd %d associated with vec %d added on epfd %d"
+                               "\n", rev->fd, vec, epfd);
+               else
+                       rc = -EPERM;
+               break;
+       case RTE_INTR_EVENT_DEL:
+               epfd_op = EPOLL_CTL_DEL;
+               rev = &intr_handle->elist[vec];
+               if (rev->status == RTE_EPOLL_INVALID) {
+                       RTE_LOG(INFO, EAL, "Event does not exist.\n");
+                       return -EPERM;
+               }
+
+               rc = rte_epoll_ctl(rev->epfd, epfd_op, rev->fd, rev);
+               if (rc)
+                       rc = -EPERM;
+               break;
+       default:
+               RTE_LOG(ERR, EAL, "event op type mismatch\n");
+               rc = -EPERM;
+       }
+
+       return rc;
+}
+#else
+int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+               int epfd, int op, unsigned int vec, void *data)
+{
+       RTE_SET_USED(intr_handle);
+       RTE_SET_USED(epfd);
+       RTE_SET_USED(op);
+       RTE_SET_USED(vec);
+       RTE_SET_USED(data);
+       return -ENOTSUP;
+}
+#endif
index 886608c..acf4be9 100644 (file)
@@ -148,4 +148,24 @@ 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.
+ * @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);
+
 #endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */
index ef95f1a..7e20d7a 100644 (file)
@@ -120,6 +120,7 @@ DPDK_2.1 {
        rte_eal_pci_write_config;
        rte_epoll_ctl;
        rte_epoll_wait;
+       rte_intr_rx_ctl;
        rte_intr_tls_epfd;
        rte_memzone_free;