[dpdk-dev,v10,03/13] eal/linux: add API to set rx interrupt event monitor
Commit Message
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>
---
v10 changes:
- add RTE_INTR_HANDLE_UIO_INTX for uio_pci_generic
v8 changes
- fix EWOULDBLOCK and EINTR processing
- add event status check
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 | 101 +++++++++++++++++++++
.../linuxapp/eal/include/exec-env/rte_interrupts.h | 20 ++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 1 +
3 files changed, 122 insertions(+)
Comments
On Tue, 2 Jun 2015 14:53:16 +0800
Cunming Liang <cunming.liang@intel.com> wrote:
> + 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 file "
> + "descriptor %d: %s\n", fd,
It is better not to split strings across multiple lines because sometimes
developers need to use tools like grep to find which file has the error
message.
Instead:
RTE_LOG(ERR, EAL,
"Error reading from fd %d: %s\n",
fd, strerror(errno));
On Tue, 2 Jun 2015 14:53:16 +0800
Cunming Liang <cunming.liang@intel.com> wrote:
> + if (!rc)
> + RTE_LOG(DEBUG, EAL, "eventfd %d associated with vec %d"
> + " is added on epfd %d\n", rev->fd, vec, epfd);
Awkward line split here. Better to keep string on one line.
RTE_LOG(DEBUG, EAL,
"eventfd %d associated with vec %d added on epfd %d\n",
rev->fd, vec, epfd);
On 6/3/2015 12:24 AM, Stephen Hemminger wrote:
> On Tue, 2 Jun 2015 14:53:16 +0800
> Cunming Liang <cunming.liang@intel.com> wrote:
>
>> + if (!rc)
>> + RTE_LOG(DEBUG, EAL, "eventfd %d associated with vec %d"
>> + " is added on epfd %d\n", rev->fd, vec, epfd);
> Awkward line split here. Better to keep string on one line.
> RTE_LOG(DEBUG, EAL,
> "eventfd %d associated with vec %d added on epfd %d\n",
> rev->fd, vec, epfd);
It's reasonable, will fix it in next version, thanks.
@@ -897,6 +897,50 @@ rte_eal_intr_init(void)
return -ret;
}
+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 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);
+ return;
+ } while (1);
+}
+
static int
eal_epoll_process_event(struct epoll_event *evs, unsigned int n,
struct rte_epoll_event *events)
@@ -1032,3 +1076,60 @@ 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)
+{
+ 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, "eventfd %d associated with vec %d"
+ " is 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;
+}
@@ -146,4 +146,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_ */
@@ -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;