DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e
@ 2015-09-24  5:33 Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
                   ` (11 more replies)
  0 siblings, 12 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

This patch series contains four major parts.

1. always reserve vector zero for misc cause in vfio mapping
2. add api to declare the capability of multiple interrupt vector support
3. fix the rx interrupt compatible issue with mbox in ixgbe/igb IOV-PF
4. add rx interrupt support in i40e PF and VF

Cunming Liang (11):
  eal/linux: vfio map misc intr to vector zero
  ixgbe: reserve intr vector zero for misc cause
  igb: reserve intr vector zero for misc cause
  eal/linux: not allow to enable zero intr efd
  eal/linux: add intr api to report multi-vector capability
  ixgbe: fix rx intr compatible issue with PF mbox
  ixgbevf: cleanup unnecessary interrupt handler
  igb: fix rx intr compatible issue with PF mbox
  i40e: add rx interrupt support
  i40evf: add rx interrupt support
  doc: release note update for intr mode

 doc/guides/rel_notes/release_2_2.rst               |   2 +
 drivers/net/e1000/igb_ethdev.c                     |  63 ++--
 drivers/net/i40e/i40e_ethdev.c                     | 359 +++++++++++++++++----
 drivers/net/i40e/i40e_ethdev.h                     |  17 +
 drivers/net/i40e/i40e_ethdev_vf.c                  | 141 +++++++-
 drivers/net/i40e/i40e_pf.c                         |   7 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                   | 144 +++------
 .../bsdapp/eal/include/exec-env/rte_interrupts.h   |   3 +-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  35 +-
 .../linuxapp/eal/include/exec-env/rte_interrupts.h |  16 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   7 +
 11 files changed, 597 insertions(+), 197 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 01/11] eal/linux: vfio map misc intr to vector zero
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e, fm10k).
The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the first vector to misc interrupt.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_interrupts.c           | 18 ++++++++++++------
 .../linuxapp/eal/include/exec-env/rte_interrupts.h     |  3 +++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 078318c..8e76a7a 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -300,8 +300,10 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {
 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
 	irq_set->start = 0;
 	fd_ptr = (int *) &irq_set->data;
-	memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
-	fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
+	fd_ptr[MISC_VEC_ID] = intr_handle->fd;
+	/* follow up with misc(0) interrupt */
+	memcpy(&fd_ptr[RX_VEC_START], intr_handle->efds,
+		sizeof(*intr_handle->efds) * intr_handle->nb_efd);
 
 	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
 
@@ -1068,10 +1070,13 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	struct rte_epoll_event *rev;
 	struct rte_epoll_data *epdata;
 	int epfd_op;
+	unsigned int efd_idx;
 	int rc = 0;
 
+	efd_idx = (vec >= RX_VEC_START) ? (vec - RX_VEC_START) : vec;
+
 	if (!intr_handle || intr_handle->nb_efd == 0 ||
-	    vec >= intr_handle->nb_efd) {
+	    efd_idx >= intr_handle->nb_efd) {
 		RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
 		return -EPERM;
 	}
@@ -1079,7 +1084,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	switch (op) {
 	case RTE_INTR_EVENT_ADD:
 		epfd_op = EPOLL_CTL_ADD;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status != RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event already been added.\n");
 			return -EEXIST;
@@ -1091,7 +1096,8 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		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);
+		rc = rte_epoll_ctl(epfd, epfd_op,
+				   intr_handle->efds[efd_idx], rev);
 		if (!rc)
 			RTE_LOG(DEBUG, EAL,
 				"efd %d associated with vec %d added on epfd %d"
@@ -1101,7 +1107,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		break;
 	case RTE_INTR_EVENT_DEL:
 		epfd_op = EPOLL_CTL_DEL;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status == RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event does not exist.\n");
 			return -EPERM;
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 45071b7..b8fd318 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
@@ -77,6 +77,9 @@ struct rte_epoll_event {
 	struct rte_epoll_data epdata;
 };
 
+#define MISC_VEC_ID                (0)
+#define RX_VEC_START               (MISC_VEC_ID + 1)
+
 /** Handle for interrupts. */
 struct rte_intr_handle {
 	union {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 02/11] ixgbe: reserve intr vector zero for misc cause
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 03/11] igb: " Cunming Liang
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ec2918c..dbc0cd4 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4249,7 +4249,8 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t queue_id, vec = 0;
+	uint32_t queue_id, base = MISC_VEC_ID;
+	uint32_t vec = MISC_VEC_ID;
 	uint32_t mask;
 	uint32_t gpie;
 
@@ -4259,6 +4260,9 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle))
+		vec = base = RX_VEC_START;
+
 	/* setup GPIE for MSI-x mode */
 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 	gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
@@ -4282,23 +4286,23 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 		/* by default, 1:1 mapping */
 		ixgbe_set_ivar_map(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
 		ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-				   intr_handle->max_intr - 1);
+				   MISC_VEC_ID);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ixgbe_set_ivar_map(hw, -1, 1, intr_handle->max_intr - 1);
+		ixgbe_set_ivar_map(hw, -1, 1, MISC_VEC_ID);
 		break;
 	default:
 		break;
 	}
-	IXGBE_WRITE_REG(hw, IXGBE_EITR(queue_id),
+	IXGBE_WRITE_REG(hw, IXGBE_EITR(MISC_VEC_ID),
 			IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF);
 
 	/* set up to autoclear timer, and the vectors */
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 03/11] igb: reserve intr vector zero for misc cause
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 848ef6e..03400f4 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -4210,7 +4210,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	uint32_t tmpval, regval, intr_mask;
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t vec = 0;
+	uint32_t vec = MISC_VEC_ID;
+	uint32_t base = MISC_VEC_ID;
+	uint32_t misc_shift = 0;
+
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	/* won't configure msix register if no mapping is done
@@ -4219,6 +4222,11 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = base = RX_VEC_START;
+		misc_shift = 1;
+	}
+
 	/* set interrupt vector for other causes */
 	if (hw->mac.type == e1000_82575) {
 		tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -4247,8 +4255,8 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 		E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
 					E1000_GPIE_PBA | E1000_GPIE_EIAME |
 					E1000_GPIE_NSICR);
-
-		intr_mask = (1 << intr_handle->max_intr) - 1;
+		intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+			misc_shift;
 		regval = E1000_READ_REG(hw, E1000_EIAC);
 		E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
 
@@ -4262,14 +4270,15 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	/* use EIAM to auto-mask when MSI-X interrupt
 	 * is asserted, this saves a register write for every interrupt
 	 */
-	intr_mask = (1 << intr_handle->nb_efd) - 1;
+	intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+		misc_shift;
 	regval = E1000_READ_REG(hw, E1000_EIAM);
 	E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
 
 	for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
 		eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 04/11] eal/linux: not allow to enable zero intr efd
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (2 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 03/11] igb: " Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

The patch adds condition check to avoid enable nothing.
In disable state, both max_intr and nb_efd are zero.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 3 ++-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  | 8 +++++++-
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

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 88d4ae1..cd8817d 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
@@ -82,8 +82,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8e76a7a..96226d6 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -45,6 +45,7 @@
 #include <sys/signalfd.h>
 #include <sys/ioctl.h>
 #include <sys/eventfd.h>
+#include <assert.h>
 
 #include <rte_common.h>
 #include <rte_interrupts.h>
@@ -1132,6 +1133,8 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
 	int fd;
 	uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
 
+	assert(nb_efd != 0);
+
 	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) {
 		for (i = 0; i < n; i++) {
 			fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
@@ -1188,5 +1191,8 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 {
-	return !!(intr_handle->max_intr - intr_handle->nb_efd);
+	if (!rte_intr_dp_is_en(intr_handle))
+		return 1;
+	else
+		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
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 b8fd318..6a2f495 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
@@ -176,8 +176,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 05/11] eal/linux: add intr api to report multi-vector capability
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (3 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it in the future.
Device drivers need to be aware of the capability.
It's better to avoid condition check on interrupt type(VFIO) everywhere, instead
a capability api is more flexible for the condition change.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9 +++++++++
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10 ++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
 3 files changed, 26 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 96226d6..c90bc4d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -1196,3 +1196,12 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	else
 		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX)
+		return 1;
+
+	return 0;
+}
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 6a2f495..a7b2be4 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
@@ -215,4 +215,14 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 dbb8fa1..cb9f4d6 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -128,3 +128,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (4 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-11-02 16:03   ` David Marchand
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 45 +++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index dbc0cd4..f180d75 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1028,6 +1028,13 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 			eth_dev->data->port_id, pci_dev->id.vendor_id,
 			pci_dev->id.device_id);
 
+	rte_intr_callback_register(&(pci_dev->intr_handle),
+				   ixgbe_dev_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&(pci_dev->intr_handle));
+
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
@@ -1704,17 +1711,19 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
-				    dev->data->nb_rx_queues * sizeof(int),
-				    0);
+				    dev->data->nb_rx_queues * sizeof(int), 0);
 		if (intr_handle->intr_vec == NULL) {
 			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
 				     " intr_vec\n", dev->data->nb_rx_queues);
@@ -1801,20 +1810,22 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 skip_link_setup:
 
-	/* check if lsc interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   ixgbe_dev_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			ixgbe_dev_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     ixgbe_dev_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		ixgbe_dev_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1926,6 +1937,12 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 	memset(filter_info->fivetuple_mask, 0,
 		sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   ixgbe_dev_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 07/11] ixgbevf: cleanup unnecessary interrupt handler
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (5 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

As ixgbe vf doesn't support lsc, the patch removes those unused code.
In addition, it does some tiny cleanup.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 85 +++++-----------------------------------
 1 file changed, 10 insertions(+), 75 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index f180d75..1d46320 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -206,8 +206,6 @@ static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_conf
 /* For Virtual Function support */
 static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
-static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_start(struct rte_eth_dev *dev);
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
@@ -223,8 +221,6 @@ static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
 static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
-static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,
-					  void *param);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
 static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
@@ -2670,30 +2666,6 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
-{
-	uint32_t eicr;
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct ixgbe_interrupt *intr =
-		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
-	/* clear all cause mask */
-	ixgbevf_intr_disable(hw);
-
-	/* read-on-clear nic registers here */
-	eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
-	PMD_DRV_LOG(INFO, "eicr %x", eicr);
-
-	intr->flags = 0;
-
-	/* set flag for async link update */
-	if (eicr & IXGBE_EICR_LSC)
-		intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
-
-	return 0;
-}
-
 /**
  * It gets and then prints the link status.
  *
@@ -2789,18 +2761,6 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
-{
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	PMD_DRV_LOG(DEBUG, "enable intr immediately");
-	ixgbevf_intr_enable(hw);
-	rte_intr_enable(&dev->pci_dev->intr_handle);
-	return 0;
-}
-
 /**
  * Interrupt handler which shall be registered for alarm callback for delayed
  * handling specific interrupt to wait for the stable nic state. As the
@@ -2863,16 +2823,6 @@ ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 	ixgbe_dev_interrupt_action(dev);
 }
 
-static void
-ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
-			      void *param)
-{
-	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
-	ixgbevf_dev_interrupt_get_status(dev);
-	ixgbevf_dev_interrupt_action(dev);
-}
-
 static int
 ixgbe_dev_led_on(struct rte_eth_dev *dev)
 {
@@ -3466,11 +3416,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	ixgbevf_dev_rxtx_start(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
@@ -3484,16 +3434,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	}
 	ixgbevf_configure_msix(dev);
 
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle))
-			rte_intr_callback_register(intr_handle,
-					ixgbevf_dev_interrupt_handler,
-					(void *)dev);
-		else
-			PMD_INIT_LOG(INFO, "lsc won't enable because of"
-				     " no intr multiplex\n");
-	}
-
 	rte_intr_enable(intr_handle);
 
 	/* Re-enable interrupt for VF */
@@ -3539,7 +3479,6 @@ static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -3551,12 +3490,6 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
 
 	/* reprogram the RAR[0] in case user changed it. */
 	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
-	pci_dev = dev->pci_dev;
-	if (pci_dev->intr_handle.intr_vec) {
-		rte_free(pci_dev->intr_handle.intr_vec);
-		pci_dev->intr_handle.intr_vec = NULL;
-	}
 }
 
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
@@ -4082,7 +4015,8 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask |= (1 << queue_id);
+	mask |= (1 << MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	rte_intr_enable(&dev->pci_dev->intr_handle);
@@ -4098,7 +4032,8 @@ ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask &= ~(1 << queue_id);
+	mask &= ~(1 << MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	return 0;
@@ -4234,7 +4169,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t q_idx;
-	uint32_t vector_idx = 0;
+	uint32_t vector_idx = MISC_VEC_ID;
 
 	/* won't configure msix register if no mapping is done
 	 * between intr vector and event fd.
@@ -4251,7 +4186,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 		intr_handle->intr_vec[q_idx] = vector_idx;
 	}
 
-	/* Configure VF Rx queue ivar */
+	/* Configure VF other cause ivar */
 	ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
 }
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 08/11] igb: fix rx intr compatible issue with PF mbox
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (6 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 09/11] i40e: add rx interrupt support Cunming Liang
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

When igb runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 44 +++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 03400f4..967506c 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -651,6 +651,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id);
 
+	rte_intr_callback_register(&(pci_dev->intr_handle),
+				   eth_igb_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&(pci_dev->intr_handle));
+
 	/* enable support intr */
 	igb_intr_enable(eth_dev);
 
@@ -929,13 +936,16 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
 				    dev->data->nb_rx_queues * sizeof(int), 0);
@@ -1028,20 +1038,22 @@ eth_igb_start(struct rte_eth_dev *dev)
 	}
 	e1000_setup_link(hw);
 
-	/* check if lsc interrupt feature is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   eth_igb_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			eth_igb_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     eth_igb_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		eth_igb_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1134,6 +1146,12 @@ eth_igb_stop(struct rte_eth_dev *dev)
 	}
 	filter_info->twotuple_mask = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   eth_igb_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 09/11] i40e: add rx interrupt support
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (7 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 10/11] i40evf: " Cunming Liang
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e PF non-IOV mode.
Per queue rx interrupt works on vfio, however on uio, all rx queues share one interrupt vector.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 319 +++++++++++++++++++++++++++++++++++------
 drivers/net/i40e/i40e_ethdev.h |   2 +
 drivers/net/i40e/i40e_pf.c     |   2 +
 3 files changed, 282 insertions(+), 41 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..33b5296 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <assert.h>
 
 #include <rte_string_fns.h>
 #include <rte_pci.h>
@@ -174,7 +175,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
 			       bool offset_loaded,
 			       uint64_t *offset,
 			       uint64_t *stat);
-static void i40e_pf_config_irq0(struct i40e_hw *hw);
+static void i40e_pf_config_irq0(struct i40e_hw *hw, int no_queue);
 static void i40e_dev_interrupt_handler(
 		__rte_unused struct rte_intr_handle *handle, void *param);
 static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
@@ -232,6 +233,10 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 					   uint32_t flags);
 static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 					   struct timespec *timestamp);
+static int i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
+					 uint16_t queue_id);
+static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
+					  uint16_t queue_id);
 
 static const struct rte_pci_id pci_id_i40e_map[] = {
 #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -265,6 +270,10 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.tx_queue_start               = i40e_dev_tx_queue_start,
 	.tx_queue_stop                = i40e_dev_tx_queue_stop,
 	.rx_queue_setup               = i40e_dev_rx_queue_setup,
+#ifdef RTE_NEXT_ABI
+	.rx_queue_intr_enable         = i40e_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable        = i40e_dev_rx_queue_intr_disable,
+#endif
 	.rx_queue_release             = i40e_dev_rx_queue_release,
 	.rx_queue_count               = i40e_dev_rx_queue_count,
 	.rx_descriptor_done           = i40e_dev_rx_descriptor_done,
@@ -579,7 +588,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		i40e_dev_interrupt_handler, (void *)dev);
 
 	/* configure and enable device interrupt */
-	i40e_pf_config_irq0(hw);
+	i40e_pf_config_irq0(hw, 1);
 	i40e_pf_enable_irq0(hw);
 
 	/* enable uio intr after callback register */
@@ -718,6 +727,8 @@ err:
 void
 i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t msix_vect = vsi->msix_intr;
 	uint16_t i;
@@ -729,15 +740,26 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	}
 
 	if (vsi->type != I40E_VSI_SRIOV) {
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), 0);
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-				msix_vect - 1), 0);
+		if (!rte_intr_allow_others(intr_handle)) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       0);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1), 0);
+		}
 	} else {
 		uint32_t reg;
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), 0);
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+			       I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
 	}
 	I40E_WRITE_FLUSH(hw);
 }
@@ -752,29 +774,26 @@ i40e_calc_itr_interval(int16_t interval)
 	return (interval/2);
 }
 
-void
-i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+static void
+__vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
+		       int base_queue, int nb_queue)
 {
+	int i;
 	uint32_t val;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
-	uint16_t msix_vect = vsi->msix_intr;
-	int i;
-
-	for (i = 0; i < vsi->nb_qps; i++)
-		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
 
 	/* Bind all RX queues to allocated MSIX interrupt */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < nb_queue; i++) {
 		val = (msix_vect << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
 			I40E_QINT_RQCTL_ITR_INDX_MASK |
-			((vsi->base_queue + i + 1) <<
-			I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+			((base_queue + i + 1) <<
+			 I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
 			(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
 			I40E_QINT_RQCTL_CAUSE_ENA_MASK;
 
-		if (i == vsi->nb_qps - 1)
+		if (i == nb_queue - 1)
 			val |= I40E_QINT_RQCTL_NEXTQ_INDX_MASK;
-		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), val);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(base_queue + i), val);
 	}
 
 	/* Write first RX queue to Link list register as the head element */
@@ -782,13 +801,26 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		uint16_t interval =
 			i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
 
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
-						(vsi->base_queue <<
-				I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-			(0x0 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
-
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-						msix_vect - 1), interval);
+		if (msix_vect == MISC_VEC_ID) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       (base_queue <<
+					I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       interval);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       (base_queue <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1),
+				       interval);
+		}
 
 #ifndef I40E_GLINT_CTL
 #define I40E_GLINT_CTL                     0x0003F800
@@ -796,7 +828,7 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 #endif
 		/* Disable auto-mask on enabling of all none-zero  interrupt */
 		I40E_WRITE_REG(hw, I40E_GLINT_CTL,
-			I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK);
+			       I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK);
 	} else {
 		uint32_t reg;
 
@@ -804,34 +836,117 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (vsi->base_queue <<
-					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
+				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
 				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
 	}
 
 	I40E_WRITE_FLUSH(hw);
 }
 
+void
+i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+{
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_vect = vsi->msix_intr;
+	uint16_t nb_msix = RTE_MIN(vsi->nb_msix, intr_handle->nb_efd);
+	uint16_t queue_idx = 0;
+	int record = 0;
+	int i;
+
+	for (i = 0; i < vsi->nb_qps; i++) {
+		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0);
+	}
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		if (vsi->type == I40E_VSI_MAIN) {
+			queue_idx = 0;
+			record = 1;
+		} else if (vsi->type == I40E_VSI_VMDQ2) {
+			struct i40e_vsi *main_vsi =
+				I40E_DEV_PRIVATE_TO_MAIN_VSI(vsi->adapter);
+			queue_idx = vsi->base_queue - main_vsi->nb_qps;
+			record = 1;
+		}
+	}
+
+	for (i = 0; i < vsi->nb_used_qps; i++) {
+		if (nb_msix <= 1) {
+			if (!rte_intr_allow_others(intr_handle))
+				/* allow to share MISC_VEC_ID */
+				msix_vect = MISC_VEC_ID;
+
+			/* no enough msix_vect, map all to one */
+			__vsi_queues_bind_intr(vsi, msix_vect,
+					       vsi->base_queue + i,
+					       vsi->nb_used_qps - i);
+			for (; !!record && i < vsi->nb_used_qps; i++)
+				intr_handle->intr_vec[queue_idx + i] =
+					msix_vect;
+			break;
+		}
+		/* 1:1 queue/msix_vect mapping */
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue + i, 1);
+		if (!!record)
+			intr_handle->intr_vec[queue_idx + i] = msix_vect;
+
+		msix_vect++;
+		nb_msix--;
+	}
+}
+
 static void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t interval = i40e_calc_itr_interval(\
-			RTE_LIBRTE_I40E_ITR_INTERVAL);
+		RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr, i;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTL0_INTENA_MASK |
+			       I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT));
+		return;
+	}
 
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1),
-					I40E_PFINT_DYN_CTLN_INTENA_MASK |
-					I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
-				(0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
-			(interval << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	for (i = 0; i < vsi->nb_msix; i++) {
+		msix_intr = vsi->msix_intr + i;
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	}
 }
 
 static void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_intr, i;
 
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+		return;
+	}
+
+	for (i = 0; i < vsi->nb_msix; i++) {
+		msix_intr = vsi->msix_intr + i;
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1), 0);
+	}
 }
 
 static inline uint8_t
@@ -941,6 +1056,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	int ret, i;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t intr_vector = 0;
 
 	hw->adapter_stopped = 0;
 
@@ -952,6 +1069,29 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		return -EINVAL;
 	}
 
+	rte_intr_disable(intr_handle);
+
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int),
+				    0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	/* Initialize VSI */
 	ret = i40e_dev_rxtx_init(pf);
 	if (ret != I40E_SUCCESS) {
@@ -960,11 +1100,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	}
 
 	/* Map queues with MSIX interrupt */
+	main_vsi->nb_used_qps = dev->data->nb_rx_queues -
+		pf->nb_cfg_vmdq_vsi * RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 	i40e_vsi_queues_bind_intr(main_vsi);
 	i40e_vsi_enable_queues_intr(main_vsi);
 
 	/* Map VMDQ VSI queues with MSIX interrupt */
 	for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
+		pf->vmdq[i].vsi->nb_used_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 		i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi);
 		i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
 	}
@@ -1001,6 +1144,22 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		goto err_up;
 	}
 
+	if (!rte_intr_allow_others(intr_handle)) {
+		rte_intr_callback_unregister(intr_handle,
+					     i40e_dev_interrupt_handler,
+					     (void *)dev);
+		/* configure and enable device interrupt */
+		i40e_pf_config_irq0(hw, 0);
+		i40e_pf_enable_irq0(hw);
+
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
+			PMD_INIT_LOG(INFO, "lsc won't enable because of"
+				     " no intr multiplex\n");
+	}
+
+	/* enable uio intr after callback register */
+	rte_intr_enable(intr_handle);
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -1016,6 +1175,7 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	struct i40e_mirror_rule *p_mirror;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	int i;
 
 	/* Disable all queues */
@@ -1047,6 +1207,18 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	}
 	pf->nb_mirror_rule = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   i40e_dev_interrupt_handler,
+					   (void *)dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static void
@@ -3073,15 +3245,30 @@ i40e_vsi_setup(struct i40e_pf *pf,
 		vsi->base_queue = I40E_FDIR_QUEUE_ID;
 
 	/* VF has MSIX interrupt in VF range, don't allocate here */
-	if (type != I40E_VSI_SRIOV) {
+	if (type == I40E_VSI_MAIN) {
+		ret = i40e_res_pool_alloc(&pf->msix_pool,
+					  RTE_MIN(vsi->nb_qps,
+						  RTE_MAX_RXTX_INTR_VEC_ID));
+		if (ret < 0) {
+			PMD_DRV_LOG(ERR, "VSI MAIN %d get heap failed %d",
+				    vsi->seid, ret);
+			goto fail_queue_alloc;
+		}
+		vsi->msix_intr = ret;
+		vsi->nb_msix = RTE_MIN(vsi->nb_qps, RTE_MAX_RXTX_INTR_VEC_ID);
+	} else if (type != I40E_VSI_SRIOV) {
 		ret = i40e_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret);
 			goto fail_queue_alloc;
 		}
 		vsi->msix_intr = ret;
-	} else
+		vsi->nb_msix = 1;
+	} else {
 		vsi->msix_intr = 0;
+		vsi->nb_msix = 0;
+	}
+
 	/* Add VSI */
 	if (type == I40E_VSI_MAIN) {
 		/* For main VSI, no need to add since it's default one */
@@ -3919,7 +4106,7 @@ i40e_pf_enable_irq0(struct i40e_hw *hw)
 }
 
 static void
-i40e_pf_config_irq0(struct i40e_hw *hw)
+i40e_pf_config_irq0(struct i40e_hw *hw, int no_queue)
 {
 	/* read pending request and disable first */
 	i40e_pf_disable_irq0(hw);
@@ -3927,9 +4114,10 @@ i40e_pf_config_irq0(struct i40e_hw *hw)
 	I40E_WRITE_REG(hw, I40E_PFINT_STAT_CTL0,
 		I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK);
 
-	/* Link no queues with irq0 */
-	I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
-		I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+	if (no_queue)
+		/* Link no queues with irq0 */
+		I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+			       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
 }
 
 static void
@@ -6298,3 +6486,52 @@ i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 
 	return  0;
 }
+
+static int
+i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr - RX_VEC_START),
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr - RX_VEC_START),
+			       0);
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 6185657..727ee2d 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -235,6 +235,7 @@ struct i40e_vsi {
 	uint16_t seid;           /* The seid of VSI itself */
 	uint16_t uplink_seid;    /* The uplink seid of this VSI */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
 	/*
@@ -243,6 +244,7 @@ struct i40e_vsi {
 	 */
 	uint16_t vsi_id;
 	uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
+	uint16_t nb_msix;   /* The max number of msix vector */
 	uint8_t enabled_tc; /* The traffic class enabled */
 };
 
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 95c960c..c1d58a8 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -554,6 +554,8 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+	vf->vsi->nb_msix = irqmap->num_vectors;
+	vf->vsi->nb_used_qps = vf->vsi->nb_qps;
 
 	/* Don't care how the TX/RX queue mapping with this vector.
 	 * Link all VF RX queues together. Only did mapping work.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 10/11] i40evf: add rx interrupt support
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (8 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 09/11] i40e: add rx interrupt support Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 11/11] doc: release note update for intr mode Cunming Liang
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e VF and some necessary change on PF IOV mode to support VF.
On PF side, running in IOV mode via uio won't allow rx interrupt which is exclusive with mbox interrupt
in single vector competition.
On VF side, one single vector is shared for all the rx queues.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    |  46 +++++++------
 drivers/net/i40e/i40e_ethdev.h    |  15 ++++
 drivers/net/i40e/i40e_ethdev_vf.c | 141 ++++++++++++++++++++++++++++++++++----
 drivers/net/i40e/i40e_pf.c        |   5 --
 4 files changed, 169 insertions(+), 38 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 33b5296..7937e37 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -75,11 +75,6 @@
 /* Maximun number of VSI */
 #define I40E_MAX_NUM_VSIS          (384UL)
 
-/* Default queue interrupt throttling time in microseconds */
-#define I40E_ITR_INDEX_DEFAULT          0
-#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
-#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
-
 #define I40E_PRE_TX_Q_CFG_WAIT_US       10 /* 10 us */
 
 /* Mask of PF interrupt causes */
@@ -764,16 +759,6 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_FLUSH(hw);
 }
 
-static inline uint16_t
-i40e_calc_itr_interval(int16_t interval)
-{
-	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
-		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
-
-	/* Convert to hardware count, as writing each 1 represents 2 us */
-	return (interval/2);
-}
-
 static void
 __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 		       int base_queue, int nb_queue)
@@ -832,13 +817,24 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 	} else {
 		uint32_t reg;
 
-		/* num_msix_vectors_vf needs to minus irq0 */
-		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
-			vsi->user_param + (msix_vect - 1);
+		if (msix_vect == MISC_VEC_ID) {
+			I40E_WRITE_REG(hw,
+				       I40E_VPINT_LNKLST0(vsi->user_param),
+				       (base_queue <<
+					I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+		} else {
+			/* num_msix_vectors_vf needs to minus irq0 */
+			reg = (hw->func_caps.num_msix_vectors_vf - 1) *
+				vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
-				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+				       (base_queue <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+		}
 	}
 
 	I40E_WRITE_FLUSH(hw);
@@ -861,6 +857,14 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0);
 	}
 
+	/* VF bind interrupt */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue, vsi->nb_qps);
+		return;
+	}
+
+	/* PF & VMDq bind interrupt */
 	if (rte_intr_dp_is_en(intr_handle)) {
 		if (vsi->type == I40E_VSI_MAIN) {
 			queue_idx = 0;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 727ee2d..52fb3f9 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -151,6 +151,11 @@ enum i40e_flxpld_layer_idx {
 	(1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
 	(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
 
+/* Default queue interrupt throttling time in microseconds */
+#define I40E_ITR_INDEX_DEFAULT          0
+#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
+#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
+
 struct i40e_adapter;
 
 /**
@@ -573,6 +578,16 @@ i40e_align_floor(int n)
 	return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n));
 }
 
+static inline uint16_t
+i40e_calc_itr_interval(int16_t interval)
+{
+	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
+		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
+
+	/* Convert to hardware count, as writing each 1 represents 2 us */
+	return (interval / 2);
+}
+
 #define I40E_VALID_FLOW(flow_type) \
 	((flow_type) == RTE_ETH_FLOW_FRAG_IPV4 || \
 	(flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index b694400..074448f 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -144,6 +144,10 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
 				      struct rte_eth_rss_conf *rss_conf);
 static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 					struct rte_eth_rss_conf *rss_conf);
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
@@ -169,6 +173,9 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.tx_queue_stop        = i40evf_dev_tx_queue_stop,
 	.rx_queue_setup       = i40e_dev_rx_queue_setup,
 	.rx_queue_release     = i40e_dev_rx_queue_release,
+	.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
+	.rx_descriptor_done   = i40e_dev_rx_descriptor_done,
 	.tx_queue_setup       = i40e_dev_tx_queue_setup,
 	.tx_queue_release     = i40e_dev_tx_queue_release,
 	.reta_update          = i40evf_dev_rss_reta_update,
@@ -700,19 +707,30 @@ i40evf_config_irq_map(struct rte_eth_dev *dev)
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_irq_map_info) + \
 		sizeof(struct i40e_virtchnl_vector_map)];
 	struct i40e_virtchnl_irq_map_info *map_info;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t vector_id;
 	int i, err;
+
+	if (rte_intr_allow_others(intr_handle))
+		vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
+	else
+		vector_id = MISC_VEC_ID;
+
 	map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer;
 	map_info->num_vectors = 1;
 	map_info->vecmap[0].rxitr_idx = RTE_LIBRTE_I40E_ITR_INTERVAL / 2;
 	map_info->vecmap[0].txitr_idx = RTE_LIBRTE_I40E_ITR_INTERVAL / 2;
 	map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id;
 	/* Alway use default dynamic MSIX interrupt */
-	map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
+	map_info->vecmap[0].vector_id = vector_id;
 	/* Don't map any tx queue */
 	map_info->vecmap[0].txq_map = 0;
 	map_info->vecmap[0].rxq_map = 0;
-	for (i = 0; i < dev->data->nb_rx_queues; i++)
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		map_info->vecmap[0].rxq_map |= 1 << i;
+		if (rte_intr_dp_is_en(intr_handle))
+			intr_handle->intr_vec[i] = vector_id;
+	}
 
 	args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
 	args.in_args = (u8 *)cmd_buffer;
@@ -1546,18 +1564,88 @@ i40evf_tx_init(struct rte_eth_dev *dev)
 }
 
 static inline void
-i40evf_enable_queues_intr(struct i40e_hw *hw)
+i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 {
-	I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
-			I40E_VFINT_DYN_CTLN1_INTENA_MASK |
-			I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+		return;
+	}
+
+	I40E_WRITE_REG(hw,
+		       I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
+		       I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+		       I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK);
 }
 
 static inline void
-i40evf_disable_queues_intr(struct i40e_hw *hw)
+i40evf_disable_queues_intr(struct rte_eth_dev *dev)
 {
-	I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
-			0);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+		return;
+	}
+
+	I40E_WRITE_REG(hw,
+		       I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
+		       0);
+}
+
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - RX_VEC_START),
+			       I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+			       I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT));
+
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - RX_VEC_START),
+			       0);
+
+	return 0;
 }
 
 static int
@@ -1565,7 +1653,9 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ether_addr mac_addr;
+	uint32_t intr_vector = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1575,6 +1665,24 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 	vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
 					dev->data->nb_tx_queues);
 
+	/* check and configure queue intr-vector mapping */
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int), 0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	if (i40evf_rx_init(dev) != 0){
 		PMD_DRV_LOG(ERR, "failed to do RX init");
 		return -1;
@@ -1604,7 +1712,9 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 		goto err_mac;
 	}
 
-	i40evf_enable_queues_intr(hw);
+	rte_intr_enable(intr_handle);
+
+	i40evf_enable_queues_intr(dev);
 	return 0;
 
 err_mac:
@@ -1616,13 +1726,20 @@ err_queue:
 static void
 i40evf_dev_stop(struct rte_eth_dev *dev)
 {
-	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	PMD_INIT_FUNC_TRACE();
 
-	i40evf_disable_queues_intr(hw);
+	i40evf_disable_queues_intr(dev);
 	i40evf_stop_queues(dev);
 	i40e_dev_clear_queues(dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index c1d58a8..cbf4e5b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -547,11 +547,6 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 		goto send_msg;
 	}
 
-	if (irqmap->vecmap[0].vector_id == 0) {
-		PMD_DRV_LOG(ERR, "DPDK host don't support use IRQ0");
-		ret = I40E_ERR_PARAM;
-		goto send_msg;
-	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
 	vf->vsi->nb_msix = irqmap->num_vectors;
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v1 11/11] doc: release note update for intr mode
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (9 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 10/11] i40evf: " Cunming Liang
@ 2015-09-24  5:33 ` Cunming Liang
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-09-24  5:33 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 682f468..73dba47 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -4,10 +4,12 @@ DPDK Release 2.2
 New Features
 ------------
 
+* Support interrupt mode on i40e
 
 Resolved Issues
 ---------------
 
+* Fix ixgbe/igb rx interrupt compatible issue with mbox
 
 Known Issues
 ------------
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e
  2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
                   ` (10 preceding siblings ...)
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 11/11] doc: release note update for intr mode Cunming Liang
@ 2015-10-30  5:27 ` Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
                     ` (11 more replies)
  11 siblings, 12 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

v2 change:
  - rebase code base
  - rework to depend on one previous patch
    patch http://dpdk.org/dev/patchwork/patch/7504/
  - always set DIS_AUTOMASK_* bit in PF to avoid ENA flag auto-clear

This patch series contains four major parts.

1. always reserve vector zero for misc cause in vfio mapping
2. add api to declare the capability of multiple interrupt vector support
3. fix the rx interrupt compatible issue with mbox in ixgbe/igb IOV-PF
4. add rx interrupt support in i40e PF and VF

Cunming Liang (11):
  eal/linux: vfio map misc intr to vector zero
  ixgbe: reserve intr vector zero for misc cause
  igb: reserve intr vector zero for misc cause
  eal/linux: not allow to enable zero intr efd
  eal/linux: add intr api to report multi-vector capability
  ixgbe: fix rx intr compatible issue with PF mbox
  ixgbevf: cleanup unnecessary interrupt handler
  igb: fix rx intr compatible issue with PF mbox
  i40e: add rx interrupt support
  i40evf: add rx interrupt support
  doc: release note update for intr mode

 doc/guides/rel_notes/release_2_2.rst               |   4 +
 drivers/net/e1000/igb_ethdev.c                     |  63 +++-
 drivers/net/i40e/i40e_ethdev.c                     | 374 +++++++++++++++++----
 drivers/net/i40e/i40e_ethdev.h                     |  17 +
 drivers/net/i40e/i40e_ethdev_vf.c                  | 143 +++++++-
 drivers/net/i40e/i40e_pf.c                         |   7 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                   | 144 +++-----
 .../bsdapp/eal/include/exec-env/rte_interrupts.h   |   3 +-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  35 +-
 .../linuxapp/eal/include/exec-env/rte_interrupts.h |  16 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   7 +
 11 files changed, 612 insertions(+), 201 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  7:11     ` He, Shaopeng
                       ` (4 more replies)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
                     ` (10 subsequent siblings)
  11 siblings, 5 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e, fm10k).
The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the first vector to misc interrupt.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_interrupts.c           | 18 ++++++++++++------
 .../linuxapp/eal/include/exec-env/rte_interrupts.h     |  3 +++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 078318c..8e76a7a 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -300,8 +300,10 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {
 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
 	irq_set->start = 0;
 	fd_ptr = (int *) &irq_set->data;
-	memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
-	fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
+	fd_ptr[MISC_VEC_ID] = intr_handle->fd;
+	/* follow up with misc(0) interrupt */
+	memcpy(&fd_ptr[RX_VEC_START], intr_handle->efds,
+		sizeof(*intr_handle->efds) * intr_handle->nb_efd);
 
 	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
 
@@ -1068,10 +1070,13 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	struct rte_epoll_event *rev;
 	struct rte_epoll_data *epdata;
 	int epfd_op;
+	unsigned int efd_idx;
 	int rc = 0;
 
+	efd_idx = (vec >= RX_VEC_START) ? (vec - RX_VEC_START) : vec;
+
 	if (!intr_handle || intr_handle->nb_efd == 0 ||
-	    vec >= intr_handle->nb_efd) {
+	    efd_idx >= intr_handle->nb_efd) {
 		RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
 		return -EPERM;
 	}
@@ -1079,7 +1084,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	switch (op) {
 	case RTE_INTR_EVENT_ADD:
 		epfd_op = EPOLL_CTL_ADD;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status != RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event already been added.\n");
 			return -EEXIST;
@@ -1091,7 +1096,8 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		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);
+		rc = rte_epoll_ctl(epfd, epfd_op,
+				   intr_handle->efds[efd_idx], rev);
 		if (!rc)
 			RTE_LOG(DEBUG, EAL,
 				"efd %d associated with vec %d added on epfd %d"
@@ -1101,7 +1107,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		break;
 	case RTE_INTR_EVENT_DEL:
 		epfd_op = EPOLL_CTL_DEL;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status == RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event does not exist.\n");
 			return -EPERM;
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 45071b7..b8fd318 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
@@ -77,6 +77,9 @@ struct rte_epoll_event {
 	struct rte_epoll_data epdata;
 };
 
+#define MISC_VEC_ID                (0)
+#define RX_VEC_START               (MISC_VEC_ID + 1)
+
 /** Handle for interrupts. */
 struct rte_intr_handle {
 	union {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 02/11] ixgbe: reserve intr vector zero for misc cause
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 03/11] igb: " Cunming Liang
                     ` (9 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4373661..4e1467c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4275,7 +4275,8 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t queue_id, vec = 0;
+	uint32_t queue_id, base = MISC_VEC_ID;
+	uint32_t vec = MISC_VEC_ID;
 	uint32_t mask;
 	uint32_t gpie;
 
@@ -4285,6 +4286,9 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle))
+		vec = base = RX_VEC_START;
+
 	/* setup GPIE for MSI-x mode */
 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 	gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
@@ -4308,23 +4312,23 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 		/* by default, 1:1 mapping */
 		ixgbe_set_ivar_map(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
 		ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-				   intr_handle->max_intr - 1);
+				   MISC_VEC_ID);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ixgbe_set_ivar_map(hw, -1, 1, intr_handle->max_intr - 1);
+		ixgbe_set_ivar_map(hw, -1, 1, MISC_VEC_ID);
 		break;
 	default:
 		break;
 	}
-	IXGBE_WRITE_REG(hw, IXGBE_EITR(queue_id),
+	IXGBE_WRITE_REG(hw, IXGBE_EITR(MISC_VEC_ID),
 			IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF);
 
 	/* set up to autoclear timer, and the vectors */
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 03/11] igb: reserve intr vector zero for misc cause
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
                     ` (8 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3ab082e..b3a802f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -4213,7 +4213,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	uint32_t tmpval, regval, intr_mask;
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t vec = 0;
+	uint32_t vec = MISC_VEC_ID;
+	uint32_t base = MISC_VEC_ID;
+	uint32_t misc_shift = 0;
+
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	/* won't configure msix register if no mapping is done
@@ -4222,6 +4225,11 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = base = RX_VEC_START;
+		misc_shift = 1;
+	}
+
 	/* set interrupt vector for other causes */
 	if (hw->mac.type == e1000_82575) {
 		tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -4250,8 +4258,8 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 		E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
 					E1000_GPIE_PBA | E1000_GPIE_EIAME |
 					E1000_GPIE_NSICR);
-
-		intr_mask = (1 << intr_handle->max_intr) - 1;
+		intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+			misc_shift;
 		regval = E1000_READ_REG(hw, E1000_EIAC);
 		E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
 
@@ -4265,14 +4273,15 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	/* use EIAM to auto-mask when MSI-X interrupt
 	 * is asserted, this saves a register write for every interrupt
 	 */
-	intr_mask = (1 << intr_handle->nb_efd) - 1;
+	intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+		misc_shift;
 	regval = E1000_READ_REG(hw, E1000_EIAM);
 	E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
 
 	for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
 		eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (2 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 03/11] igb: " Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  7:11     ` He, Shaopeng
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
                     ` (7 subsequent siblings)
  11 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

The patch adds condition check to avoid enable nothing.
In disable state, both max_intr and nb_efd are zero.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 3 ++-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  | 8 +++++++-
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

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 88d4ae1..cd8817d 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
@@ -82,8 +82,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8e76a7a..96226d6 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -45,6 +45,7 @@
 #include <sys/signalfd.h>
 #include <sys/ioctl.h>
 #include <sys/eventfd.h>
+#include <assert.h>
 
 #include <rte_common.h>
 #include <rte_interrupts.h>
@@ -1132,6 +1133,8 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
 	int fd;
 	uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
 
+	assert(nb_efd != 0);
+
 	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) {
 		for (i = 0; i < n; i++) {
 			fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
@@ -1188,5 +1191,8 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 {
-	return !!(intr_handle->max_intr - intr_handle->nb_efd);
+	if (!rte_intr_dp_is_en(intr_handle))
+		return 1;
+	else
+		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
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 b8fd318..6a2f495 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
@@ -176,8 +176,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (3 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  7:13     ` He, Shaopeng
  2015-11-02 15:59     ` David Marchand
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
                     ` (6 subsequent siblings)
  11 siblings, 2 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it in the future.
Device drivers need to be aware of the capability.
It's better to avoid condition check on interrupt type(VFIO) everywhere, instead
a capability api is more flexible for the condition change.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9 +++++++++
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10 ++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
 3 files changed, 26 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 96226d6..c90bc4d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -1196,3 +1196,12 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	else
 		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX)
+		return 1;
+
+	return 0;
+}
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 6a2f495..a7b2be4 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
@@ -215,4 +215,14 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 dbb8fa1..cb9f4d6 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -128,3 +128,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (4 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
                     ` (5 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 45 +++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4e1467c..366923f 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1032,6 +1032,13 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 			eth_dev->data->port_id, pci_dev->id.vendor_id,
 			pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   ixgbe_dev_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
@@ -1708,17 +1715,19 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
-				    dev->data->nb_rx_queues * sizeof(int),
-				    0);
+				    dev->data->nb_rx_queues * sizeof(int), 0);
 		if (intr_handle->intr_vec == NULL) {
 			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
 				     " intr_vec\n", dev->data->nb_rx_queues);
@@ -1805,20 +1814,22 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 skip_link_setup:
 
-	/* check if lsc interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   ixgbe_dev_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			ixgbe_dev_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     ixgbe_dev_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		ixgbe_dev_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1930,6 +1941,12 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 	memset(filter_info->fivetuple_mask, 0,
 		sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   ixgbe_dev_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (5 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-11-02 16:06     ` David Marchand
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
                     ` (4 subsequent siblings)
  11 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

As ixgbe vf doesn't support lsc, the patch removes those unused code.
In addition, it does some tiny cleanup.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 85 +++++-----------------------------------
 1 file changed, 10 insertions(+), 75 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 366923f..794171c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -206,8 +206,6 @@ static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_conf
 /* For Virtual Function support */
 static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
-static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_start(struct rte_eth_dev *dev);
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
@@ -223,8 +221,6 @@ static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
 static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
-static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,
-					  void *param);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
 static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
@@ -2681,30 +2677,6 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
-{
-	uint32_t eicr;
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct ixgbe_interrupt *intr =
-		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
-	/* clear all cause mask */
-	ixgbevf_intr_disable(hw);
-
-	/* read-on-clear nic registers here */
-	eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
-	PMD_DRV_LOG(INFO, "eicr %x", eicr);
-
-	intr->flags = 0;
-
-	/* set flag for async link update */
-	if (eicr & IXGBE_EICR_LSC)
-		intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
-
-	return 0;
-}
-
 /**
  * It gets and then prints the link status.
  *
@@ -2800,18 +2772,6 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
-{
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	PMD_DRV_LOG(DEBUG, "enable intr immediately");
-	ixgbevf_intr_enable(hw);
-	rte_intr_enable(&dev->pci_dev->intr_handle);
-	return 0;
-}
-
 /**
  * Interrupt handler which shall be registered for alarm callback for delayed
  * handling specific interrupt to wait for the stable nic state. As the
@@ -2874,16 +2834,6 @@ ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 	ixgbe_dev_interrupt_action(dev);
 }
 
-static void
-ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
-			      void *param)
-{
-	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
-	ixgbevf_dev_interrupt_get_status(dev);
-	ixgbevf_dev_interrupt_action(dev);
-}
-
 static int
 ixgbe_dev_led_on(struct rte_eth_dev *dev)
 {
@@ -3492,11 +3442,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	ixgbevf_dev_rxtx_start(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
@@ -3510,16 +3460,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	}
 	ixgbevf_configure_msix(dev);
 
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle))
-			rte_intr_callback_register(intr_handle,
-					ixgbevf_dev_interrupt_handler,
-					(void *)dev);
-		else
-			PMD_INIT_LOG(INFO, "lsc won't enable because of"
-				     " no intr multiplex\n");
-	}
-
 	rte_intr_enable(intr_handle);
 
 	/* Re-enable interrupt for VF */
@@ -3565,7 +3505,6 @@ static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -3577,12 +3516,6 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
 
 	/* reprogram the RAR[0] in case user changed it. */
 	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
-	pci_dev = dev->pci_dev;
-	if (pci_dev->intr_handle.intr_vec) {
-		rte_free(pci_dev->intr_handle.intr_vec);
-		pci_dev->intr_handle.intr_vec = NULL;
-	}
 }
 
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
@@ -4108,7 +4041,8 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask |= (1 << queue_id);
+	mask |= (1 << MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	rte_intr_enable(&dev->pci_dev->intr_handle);
@@ -4124,7 +4058,8 @@ ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask &= ~(1 << queue_id);
+	mask &= ~(1 << MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	return 0;
@@ -4260,7 +4195,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t q_idx;
-	uint32_t vector_idx = 0;
+	uint32_t vector_idx = MISC_VEC_ID;
 
 	/* won't configure msix register if no mapping is done
 	 * between intr vector and event fd.
@@ -4277,7 +4212,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 		intr_handle->intr_vec[q_idx] = vector_idx;
 	}
 
-	/* Configure VF Rx queue ivar */
+	/* Configure VF other cause ivar */
 	ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
 }
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 08/11] igb: fix rx intr compatible issue with PF mbox
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (6 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support Cunming Liang
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

When igb runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 44 +++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index b3a802f..2494fc8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -650,6 +650,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   eth_igb_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	igb_intr_enable(eth_dev);
 
@@ -928,13 +935,16 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
 				    dev->data->nb_rx_queues * sizeof(int), 0);
@@ -1027,20 +1037,22 @@ eth_igb_start(struct rte_eth_dev *dev)
 	}
 	e1000_setup_link(hw);
 
-	/* check if lsc interrupt feature is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   eth_igb_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			eth_igb_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     eth_igb_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		eth_igb_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1133,6 +1145,12 @@ eth_igb_stop(struct rte_eth_dev *dev)
 	}
 	filter_info->twotuple_mask = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   eth_igb_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (7 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  7:33     ` Zhang, Helin
  2015-10-30  7:35     ` Wu, Jingjing
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 10/11] i40evf: " Cunming Liang
                     ` (2 subsequent siblings)
  11 siblings, 2 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

v2 changes:
    - add write flush
    - always set DIS_AUTOMASK_* bit

The patch enables rx interrupt support on i40e PF non-IOV mode.
Per queue rx interrupt works on vfio, however on uio, all rx queues share one interrupt vector.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 342 +++++++++++++++++++++++++++++++++++------
 drivers/net/i40e/i40e_ethdev.h |   2 +
 drivers/net/i40e/i40e_pf.c     |   2 +
 3 files changed, 298 insertions(+), 48 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..d4a663c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <assert.h>
 
 #include <rte_string_fns.h>
 #include <rte_pci.h>
@@ -174,7 +175,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
 			       bool offset_loaded,
 			       uint64_t *offset,
 			       uint64_t *stat);
-static void i40e_pf_config_irq0(struct i40e_hw *hw);
+static void i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue);
 static void i40e_dev_interrupt_handler(
 		__rte_unused struct rte_intr_handle *handle, void *param);
 static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
@@ -232,6 +233,10 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 					   uint32_t flags);
 static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 					   struct timespec *timestamp);
+static int i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
+					 uint16_t queue_id);
+static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
+					  uint16_t queue_id);
 
 static const struct rte_pci_id pci_id_i40e_map[] = {
 #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -265,6 +270,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.tx_queue_start               = i40e_dev_tx_queue_start,
 	.tx_queue_stop                = i40e_dev_tx_queue_stop,
 	.rx_queue_setup               = i40e_dev_rx_queue_setup,
+	.rx_queue_intr_enable         = i40e_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable        = i40e_dev_rx_queue_intr_disable,
 	.rx_queue_release             = i40e_dev_rx_queue_release,
 	.rx_queue_count               = i40e_dev_rx_queue_count,
 	.rx_descriptor_done           = i40e_dev_rx_descriptor_done,
@@ -579,7 +586,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		i40e_dev_interrupt_handler, (void *)dev);
 
 	/* configure and enable device interrupt */
-	i40e_pf_config_irq0(hw);
+	i40e_pf_config_irq0(hw, TRUE);
 	i40e_pf_enable_irq0(hw);
 
 	/* enable uio intr after callback register */
@@ -718,6 +725,8 @@ err:
 void
 i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t msix_vect = vsi->msix_intr;
 	uint16_t i;
@@ -729,15 +738,26 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	}
 
 	if (vsi->type != I40E_VSI_SRIOV) {
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), 0);
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-				msix_vect - 1), 0);
+		if (!rte_intr_allow_others(intr_handle)) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       0);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1), 0);
+		}
 	} else {
 		uint32_t reg;
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), 0);
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+			       I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
 	}
 	I40E_WRITE_FLUSH(hw);
 }
@@ -752,29 +772,26 @@ i40e_calc_itr_interval(int16_t interval)
 	return (interval/2);
 }
 
-void
-i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+static void
+__vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
+		       int base_queue, int nb_queue)
 {
+	int i;
 	uint32_t val;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
-	uint16_t msix_vect = vsi->msix_intr;
-	int i;
-
-	for (i = 0; i < vsi->nb_qps; i++)
-		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
 
 	/* Bind all RX queues to allocated MSIX interrupt */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < nb_queue; i++) {
 		val = (msix_vect << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
 			I40E_QINT_RQCTL_ITR_INDX_MASK |
-			((vsi->base_queue + i + 1) <<
-			I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+			((base_queue + i + 1) <<
+			 I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
 			(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
 			I40E_QINT_RQCTL_CAUSE_ENA_MASK;
 
-		if (i == vsi->nb_qps - 1)
+		if (i == nb_queue - 1)
 			val |= I40E_QINT_RQCTL_NEXTQ_INDX_MASK;
-		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), val);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(base_queue + i), val);
 	}
 
 	/* Write first RX queue to Link list register as the head element */
@@ -782,21 +799,26 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		uint16_t interval =
 			i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
 
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
-						(vsi->base_queue <<
-				I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-			(0x0 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
-
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-						msix_vect - 1), interval);
-
-#ifndef I40E_GLINT_CTL
-#define I40E_GLINT_CTL                     0x0003F800
-#define I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK 0x4
-#endif
-		/* Disable auto-mask on enabling of all none-zero  interrupt */
-		I40E_WRITE_REG(hw, I40E_GLINT_CTL,
-			I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK);
+		if (msix_vect == MISC_VEC_ID) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       (base_queue <<
+					I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       interval);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       (base_queue <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1),
+				       interval);
+		}
 	} else {
 		uint32_t reg;
 
@@ -804,34 +826,134 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (vsi->base_queue <<
-					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
+				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
 				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
 	}
 
 	I40E_WRITE_FLUSH(hw);
 }
 
+void
+i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+{
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_vect = vsi->msix_intr;
+	uint16_t nb_msix = RTE_MIN(vsi->nb_msix, intr_handle->nb_efd);
+	uint16_t queue_idx = 0;
+	int record = 0;
+	uint32_t val;
+	int i;
+
+	for (i = 0; i < vsi->nb_qps; i++) {
+		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0);
+	}
+
+	/* INTENA flag is not auto-cleared for interrupt */
+	val = I40E_READ_REG(hw, I40E_GLINT_CTL);
+	val |= I40E_GLINT_CTL_DIS_AUTOMASK_PF0_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK;
+	I40E_WRITE_REG(hw, I40E_GLINT_CTL, val);
+
+	/* VF bind interrupt */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue, vsi->nb_qps);
+		return;
+	}
+
+	/* PF & VMDq bind interrupt */
+	if (rte_intr_dp_is_en(intr_handle)) {
+		if (vsi->type == I40E_VSI_MAIN) {
+			queue_idx = 0;
+			record = 1;
+		} else if (vsi->type == I40E_VSI_VMDQ2) {
+			struct i40e_vsi *main_vsi =
+				I40E_DEV_PRIVATE_TO_MAIN_VSI(vsi->adapter);
+			queue_idx = vsi->base_queue - main_vsi->nb_qps;
+			record = 1;
+		}
+	}
+
+	for (i = 0; i < vsi->nb_used_qps; i++) {
+		if (nb_msix <= 1) {
+			if (!rte_intr_allow_others(intr_handle))
+				/* allow to share MISC_VEC_ID */
+				msix_vect = MISC_VEC_ID;
+
+			/* no enough msix_vect, map all to one */
+			__vsi_queues_bind_intr(vsi, msix_vect,
+					       vsi->base_queue + i,
+					       vsi->nb_used_qps - i);
+			for (; !!record && i < vsi->nb_used_qps; i++)
+				intr_handle->intr_vec[queue_idx + i] =
+					msix_vect;
+			break;
+		}
+		/* 1:1 queue/msix_vect mapping */
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue + i, 1);
+		if (!!record)
+			intr_handle->intr_vec[queue_idx + i] = msix_vect;
+
+		msix_vect++;
+		nb_msix--;
+	}
+}
+
 static void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t interval = i40e_calc_itr_interval(\
-			RTE_LIBRTE_I40E_ITR_INTERVAL);
-
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1),
-					I40E_PFINT_DYN_CTLN_INTENA_MASK |
-					I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+		RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr, i;
+
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				I40E_PFINT_DYN_CTLN_INTENA_MASK |
+				I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
 				(0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
-			(interval << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+				(interval <<
+				 I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTL0_INTENA_MASK |
+			       I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_intr, i;
 
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				       0);
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline uint8_t
@@ -941,6 +1063,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	int ret, i;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t intr_vector = 0;
 
 	hw->adapter_stopped = 0;
 
@@ -952,6 +1076,29 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		return -EINVAL;
 	}
 
+	rte_intr_disable(intr_handle);
+
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int),
+				    0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	/* Initialize VSI */
 	ret = i40e_dev_rxtx_init(pf);
 	if (ret != I40E_SUCCESS) {
@@ -960,11 +1107,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	}
 
 	/* Map queues with MSIX interrupt */
+	main_vsi->nb_used_qps = dev->data->nb_rx_queues -
+		pf->nb_cfg_vmdq_vsi * RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 	i40e_vsi_queues_bind_intr(main_vsi);
 	i40e_vsi_enable_queues_intr(main_vsi);
 
 	/* Map VMDQ VSI queues with MSIX interrupt */
 	for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
+		pf->vmdq[i].vsi->nb_used_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 		i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi);
 		i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
 	}
@@ -1001,6 +1151,22 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		goto err_up;
 	}
 
+	if (!rte_intr_allow_others(intr_handle)) {
+		rte_intr_callback_unregister(intr_handle,
+					     i40e_dev_interrupt_handler,
+					     (void *)dev);
+		/* configure and enable device interrupt */
+		i40e_pf_config_irq0(hw, FALSE);
+		i40e_pf_enable_irq0(hw);
+
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
+			PMD_INIT_LOG(INFO, "lsc won't enable because of"
+				     " no intr multiplex\n");
+	}
+
+	/* enable uio intr after callback register */
+	rte_intr_enable(intr_handle);
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -1016,6 +1182,7 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	struct i40e_mirror_rule *p_mirror;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	int i;
 
 	/* Disable all queues */
@@ -1047,6 +1214,18 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	}
 	pf->nb_mirror_rule = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   i40e_dev_interrupt_handler,
+					   (void *)dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static void
@@ -3073,15 +3252,30 @@ i40e_vsi_setup(struct i40e_pf *pf,
 		vsi->base_queue = I40E_FDIR_QUEUE_ID;
 
 	/* VF has MSIX interrupt in VF range, don't allocate here */
-	if (type != I40E_VSI_SRIOV) {
+	if (type == I40E_VSI_MAIN) {
+		ret = i40e_res_pool_alloc(&pf->msix_pool,
+					  RTE_MIN(vsi->nb_qps,
+						  RTE_MAX_RXTX_INTR_VEC_ID));
+		if (ret < 0) {
+			PMD_DRV_LOG(ERR, "VSI MAIN %d get heap failed %d",
+				    vsi->seid, ret);
+			goto fail_queue_alloc;
+		}
+		vsi->msix_intr = ret;
+		vsi->nb_msix = RTE_MIN(vsi->nb_qps, RTE_MAX_RXTX_INTR_VEC_ID);
+	} else if (type != I40E_VSI_SRIOV) {
 		ret = i40e_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret);
 			goto fail_queue_alloc;
 		}
 		vsi->msix_intr = ret;
-	} else
+		vsi->nb_msix = 1;
+	} else {
 		vsi->msix_intr = 0;
+		vsi->nb_msix = 0;
+	}
+
 	/* Add VSI */
 	if (type == I40E_VSI_MAIN) {
 		/* For main VSI, no need to add since it's default one */
@@ -3919,7 +4113,7 @@ i40e_pf_enable_irq0(struct i40e_hw *hw)
 }
 
 static void
-i40e_pf_config_irq0(struct i40e_hw *hw)
+i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue)
 {
 	/* read pending request and disable first */
 	i40e_pf_disable_irq0(hw);
@@ -3927,9 +4121,10 @@ i40e_pf_config_irq0(struct i40e_hw *hw)
 	I40E_WRITE_REG(hw, I40E_PFINT_STAT_CTL0,
 		I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK);
 
-	/* Link no queues with irq0 */
-	I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
-		I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+	if (no_queue)
+		/* Link no queues with irq0 */
+		I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+			       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
 }
 
 static void
@@ -6298,3 +6493,54 @@ i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 
 	return  0;
 }
+
+static int
+i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr - RX_VEC_START),
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr - RX_VEC_START),
+			       0);
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index d42487d..20d52f8 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -240,6 +240,7 @@ struct i40e_vsi {
 	uint16_t seid;           /* The seid of VSI itself */
 	uint16_t uplink_seid;    /* The uplink seid of this VSI */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
 	/*
@@ -248,6 +249,7 @@ struct i40e_vsi {
 	 */
 	uint16_t vsi_id;
 	uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
+	uint16_t nb_msix;   /* The max number of msix vector */
 	uint8_t enabled_tc; /* The traffic class enabled */
 };
 
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 95c960c..c1d58a8 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -554,6 +554,8 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+	vf->vsi->nb_msix = irqmap->num_vectors;
+	vf->vsi->nb_used_qps = vf->vsi->nb_qps;
 
 	/* Don't care how the TX/RX queue mapping with this vector.
 	 * Link all VF RX queues together. Only did mapping work.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v2 10/11] i40evf: add rx interrupt support
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (8 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  7:36     ` Wu, Jingjing
  2015-10-30  7:38     ` Zhang, Helin
  2015-10-30  5:27   ` [dpdk-dev] [PATCH 11/11] doc: release note update for intr mode Cunming Liang
  2015-10-30  8:21   ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Zhang, Helin
  11 siblings, 2 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

v2 changes:
  - turn on intr only when rxq flag is set
  - rework base on patch http://dpdk.org/dev/patchwork/patch/7504/

The patch enables rx interrupt support on i40e VF and some necessary change on PF IOV mode to support VF.
On PF side, running in IOV mode via uio won't allow rx interrupt which is exclusive with mbox interrupt
in single vector competition.
On VF side, one single vector is shared for all the rx queues.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    |  38 +++++-----
 drivers/net/i40e/i40e_ethdev.h    |  15 ++++
 drivers/net/i40e/i40e_ethdev_vf.c | 143 +++++++++++++++++++++++++++++++++++---
 drivers/net/i40e/i40e_pf.c        |   5 --
 4 files changed, 166 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index d4a663c..40ed852 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -75,11 +75,6 @@
 /* Maximun number of VSI */
 #define I40E_MAX_NUM_VSIS          (384UL)
 
-/* Default queue interrupt throttling time in microseconds */
-#define I40E_ITR_INDEX_DEFAULT          0
-#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
-#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
-
 #define I40E_PRE_TX_Q_CFG_WAIT_US       10 /* 10 us */
 
 /* Mask of PF interrupt causes */
@@ -762,16 +757,6 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_FLUSH(hw);
 }
 
-static inline uint16_t
-i40e_calc_itr_interval(int16_t interval)
-{
-	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
-		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
-
-	/* Convert to hardware count, as writing each 1 represents 2 us */
-	return (interval/2);
-}
-
 static void
 __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 		       int base_queue, int nb_queue)
@@ -822,13 +807,24 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 	} else {
 		uint32_t reg;
 
-		/* num_msix_vectors_vf needs to minus irq0 */
-		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
-			vsi->user_param + (msix_vect - 1);
+		if (msix_vect == MISC_VEC_ID) {
+			I40E_WRITE_REG(hw,
+				       I40E_VPINT_LNKLST0(vsi->user_param),
+				       (base_queue <<
+					I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+		} else {
+			/* num_msix_vectors_vf needs to minus irq0 */
+			reg = (hw->func_caps.num_msix_vectors_vf - 1) *
+				vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
-				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+				       (base_queue <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+		}
 	}
 
 	I40E_WRITE_FLUSH(hw);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 20d52f8..eeff6d7 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -156,6 +156,11 @@ enum i40e_flxpld_layer_idx {
 	(1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
 	(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
 
+/* Default queue interrupt throttling time in microseconds */
+#define I40E_ITR_INDEX_DEFAULT          0
+#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
+#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
+
 struct i40e_adapter;
 
 /**
@@ -578,6 +583,16 @@ i40e_align_floor(int n)
 	return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n));
 }
 
+static inline uint16_t
+i40e_calc_itr_interval(int16_t interval)
+{
+	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
+		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
+
+	/* Convert to hardware count, as writing each 1 represents 2 us */
+	return (interval / 2);
+}
+
 #define I40E_VALID_FLOW(flow_type) \
 	((flow_type) == RTE_ETH_FLOW_FRAG_IPV4 || \
 	(flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 176a2f6..4fdb401 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -145,6 +145,10 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
 				      struct rte_eth_rss_conf *rss_conf);
 static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 					struct rte_eth_rss_conf *rss_conf);
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
@@ -170,6 +174,9 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.tx_queue_stop        = i40evf_dev_tx_queue_stop,
 	.rx_queue_setup       = i40e_dev_rx_queue_setup,
 	.rx_queue_release     = i40e_dev_rx_queue_release,
+	.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
+	.rx_descriptor_done   = i40e_dev_rx_descriptor_done,
 	.tx_queue_setup       = i40e_dev_tx_queue_setup,
 	.tx_queue_release     = i40e_dev_tx_queue_release,
 	.reta_update          = i40evf_dev_rss_reta_update,
@@ -712,22 +719,33 @@ i40evf_config_irq_map(struct rte_eth_dev *dev)
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_irq_map_info) + \
 		sizeof(struct i40e_virtchnl_vector_map)];
 	struct i40e_virtchnl_irq_map_info *map_info;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t vector_id;
 	int i, err;
+
+	if (rte_intr_allow_others(intr_handle)) {
+		if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
+		else
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
+	} else {
+		vector_id = MISC_VEC_ID;
+	}
+
 	map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer;
 	map_info->num_vectors = 1;
 	map_info->vecmap[0].rxitr_idx = I40E_QINT_RQCTL_MSIX_INDX_NOITR;
 	map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id;
 	/* Alway use default dynamic MSIX interrupt */
-	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
-	else
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
-
+	map_info->vecmap[0].vector_id = vector_id;
 	/* Don't map any tx queue */
 	map_info->vecmap[0].txq_map = 0;
 	map_info->vecmap[0].rxq_map = 0;
-	for (i = 0; i < dev->data->nb_rx_queues; i++)
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		map_info->vecmap[0].rxq_map |= 1 << i;
+		if (rte_intr_dp_is_en(intr_handle))
+			intr_handle->intr_vec[i] = vector_id;
+	}
 
 	args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
 	args.in_args = (u8 *)cmd_buffer;
@@ -1565,6 +1583,16 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		/* To support DPDK PF host */
@@ -1577,6 +1605,8 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
 				I40E_VFINT_DYN_CTL01_INTENA_MASK |
 				I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline void
@@ -1584,14 +1614,76 @@ i40evf_disable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		I40E_WRITE_REG(hw,
-			I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
-			0);
+			       I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR
+						    - 1),
+			       0);
 	else
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
 
+	I40E_WRITE_FLUSH(hw);
+}
+
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - RX_VEC_START),
+			       I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+			       I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - RX_VEC_START),
+			       0);
+
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
 }
 
 static int
@@ -1599,7 +1691,9 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ether_addr mac_addr;
+	uint32_t intr_vector = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1609,6 +1703,24 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 	vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
 					dev->data->nb_tx_queues);
 
+	/* check and configure queue intr-vector mapping */
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int), 0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	if (i40evf_rx_init(dev) != 0){
 		PMD_DRV_LOG(ERR, "failed to do RX init");
 		return -1;
@@ -1638,6 +1750,10 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 		goto err_mac;
 	}
 
+	/* vf don't allow intr except for rxq intr */
+	if (dev->data->dev_conf.intr_conf.rxq != 0)
+		rte_intr_enable(intr_handle);
+
 	i40evf_enable_queues_intr(dev);
 	return 0;
 
@@ -1650,11 +1766,20 @@ err_queue:
 static void
 i40evf_dev_stop(struct rte_eth_dev *dev)
 {
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
 	PMD_INIT_FUNC_TRACE();
 
-	i40evf_disable_queues_intr(dev);
 	i40evf_stop_queues(dev);
+	i40evf_disable_queues_intr(dev);
 	i40e_dev_clear_queues(dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index c1d58a8..cbf4e5b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -547,11 +547,6 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 		goto send_msg;
 	}
 
-	if (irqmap->vecmap[0].vector_id == 0) {
-		PMD_DRV_LOG(ERR, "DPDK host don't support use IRQ0");
-		ret = I40E_ERR_PARAM;
-		goto send_msg;
-	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
 	vf->vsi->nb_msix = irqmap->num_vectors;
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH 11/11] doc: release note update for intr mode
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (9 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 10/11] i40evf: " Cunming Liang
@ 2015-10-30  5:27   ` Cunming Liang
  2015-10-30  8:21   ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Zhang, Helin
  11 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-10-30  5:27 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index be6f827..01bd4bb 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -23,6 +23,7 @@ New Features
 
 * **Added vhost-user multiple queue support.**
 
+* **Added interrupt mode support on i40e.**
 
 Resolved Issues
 ---------------
@@ -72,6 +73,9 @@ Drivers
 
   Fixed issue when releasing null control queue.
 
+* **ixgbe: Fixed PF rx interrupt compatible issue with mbox.**
+
+* **igb: Fixed PF rx interrupt compatible issue with mbox.**
 
 Libraries
 ~~~~~~~~~
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
@ 2015-10-30  7:11     ` He, Shaopeng
  2015-10-30  7:33     ` Zhang, Helin
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 79+ messages in thread
From: He, Shaopeng @ 2015-10-30  7:11 UTC (permalink / raw)
  To: Liang, Cunming, dev


> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
> 
> During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd,
> misc_fd}.
> The vector number of misc is indeterminable which is ugly to some NIC(e.g.
> i40e, fm10k).
> The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve
> the first vector to misc interrupt.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by : Shaopeng He <shaopeng.he@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-10-30  7:11     ` He, Shaopeng
  0 siblings, 0 replies; 79+ messages in thread
From: He, Shaopeng @ 2015-10-30  7:11 UTC (permalink / raw)
  To: Liang, Cunming, dev


> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd
> 
> The patch adds condition check to avoid enable nothing.
> In disable state, both max_intr and nb_efd are zero.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by : Shaopeng He <shaopeng.he@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
@ 2015-10-30  7:13     ` He, Shaopeng
  2015-11-02 15:59     ` David Marchand
  1 sibling, 0 replies; 79+ messages in thread
From: He, Shaopeng @ 2015-10-30  7:13 UTC (permalink / raw)
  To: Liang, Cunming, dev


> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 05/11] eal/linux: add intr api to report multi-vector
> capability
> 
> VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it in
> the future.
> Device drivers need to be aware of the capability.
> It's better to avoid condition check on interrupt type(VFIO) everywhere,
> instead
> a capability api is more flexible for the condition change.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support Cunming Liang
@ 2015-10-30  7:33     ` Zhang, Helin
  2015-10-30  7:35     ` Wu, Jingjing
  1 sibling, 0 replies; 79+ messages in thread
From: Zhang, Helin @ 2015-10-30  7:33 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 09/11] i40e: add rx interrupt support
> 
> v2 changes:
>     - add write flush
>     - always set DIS_AUTOMASK_* bit
> 
> The patch enables rx interrupt support on i40e PF non-IOV mode.
> Per queue rx interrupt works on vfio, however on uio, all rx queues share one
> interrupt vector.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
  2015-10-30  7:11     ` He, Shaopeng
@ 2015-10-30  7:33     ` Zhang, Helin
  2015-10-30 14:22     ` Liang, Cunming
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 79+ messages in thread
From: Zhang, Helin @ 2015-10-30  7:33 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
> 
> During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
> The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e,
> fm10k).
> The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the
> first vector to misc interrupt.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support Cunming Liang
  2015-10-30  7:33     ` Zhang, Helin
@ 2015-10-30  7:35     ` Wu, Jingjing
  1 sibling, 0 replies; 79+ messages in thread
From: Wu, Jingjing @ 2015-10-30  7:35 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 09/11] i40e: add rx interrupt support
> 
> v2 changes:
>     - add write flush
>     - always set DIS_AUTOMASK_* bit
> 
> The patch enables rx interrupt support on i40e PF non-IOV mode.
> Per queue rx interrupt works on vfio, however on uio, all rx queues share
> one interrupt vector.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> ---
Acked-by: Jingjing Wu <jingjing.wu@intel.com>

>  drivers/net/i40e/i40e_ethdev.c | 342
> +++++++++++++++++++++++++++++++++++------
>  drivers/net/i40e/i40e_ethdev.h |   2 +
>  drivers/net/i40e/i40e_pf.c     |   2 +
>  3 files changed, 298 insertions(+), 48 deletions(-)

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 10/11] i40evf: add rx interrupt support
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 10/11] i40evf: " Cunming Liang
@ 2015-10-30  7:36     ` Wu, Jingjing
  2015-10-30  7:38     ` Zhang, Helin
  1 sibling, 0 replies; 79+ messages in thread
From: Wu, Jingjing @ 2015-10-30  7:36 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 10/11] i40evf: add rx interrupt support
> 
> v2 changes:
>   - turn on intr only when rxq flag is set
>   - rework base on patch http://dpdk.org/dev/patchwork/patch/7504/
> 
> The patch enables rx interrupt support on i40e VF and some necessary
> change on PF IOV mode to support VF.
> On PF side, running in IOV mode via uio won't allow rx interrupt which is
> exclusive with mbox interrupt in single vector competition.
> On VF side, one single vector is shared for all the rx queues.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> ---

Acked-by: Jingjing Wu <jingjing.wu@intel.com>

Just note that http://dpdk.org/dev/patchwork/patch/7504/ is already replace
by http://dpdk.org/dev/patchwork/patch/7790/ for few code style fix.

>  drivers/net/i40e/i40e_ethdev.c    |  38 +++++-----
>  drivers/net/i40e/i40e_ethdev.h    |  15 ++++
>  drivers/net/i40e/i40e_ethdev_vf.c | 143
> +++++++++++++++++++++++++++++++++++---
>  drivers/net/i40e/i40e_pf.c        |   5 --
>  4 files changed, 166 insertions(+), 35 deletions(-)
> 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 10/11] i40evf: add rx interrupt support
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 10/11] i40evf: " Cunming Liang
  2015-10-30  7:36     ` Wu, Jingjing
@ 2015-10-30  7:38     ` Zhang, Helin
  1 sibling, 0 replies; 79+ messages in thread
From: Zhang, Helin @ 2015-10-30  7:38 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 10/11] i40evf: add rx interrupt support
> 
> v2 changes:
>   - turn on intr only when rxq flag is set
>   - rework base on patch http://dpdk.org/dev/patchwork/patch/7504/
> 
> The patch enables rx interrupt support on i40e VF and some necessary change on
> PF IOV mode to support VF.
> On PF side, running in IOV mode via uio won't allow rx interrupt which is exclusive
> with mbox interrupt in single vector competition.
> On VF side, one single vector is shared for all the rx queues.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e
  2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
                     ` (10 preceding siblings ...)
  2015-10-30  5:27   ` [dpdk-dev] [PATCH 11/11] doc: release note update for intr mode Cunming Liang
@ 2015-10-30  8:21   ` Zhang, Helin
  11 siblings, 0 replies; 79+ messages in thread
From: Zhang, Helin @ 2015-10-30  8:21 UTC (permalink / raw)
  To: Liang, Cunming, dev



> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 00/11] interrupt mode for i40e
> 
> v2 change:
>   - rebase code base
>   - rework to depend on one previous patch
>     patch http://dpdk.org/dev/patchwork/patch/7504/
>   - always set DIS_AUTOMASK_* bit in PF to avoid ENA flag auto-clear
> 
> This patch series contains four major parts.
> 
> 1. always reserve vector zero for misc cause in vfio mapping 2. add api to declare
> the capability of multiple interrupt vector support 3. fix the rx interrupt
> compatible issue with mbox in ixgbe/igb IOV-PF 4. add rx interrupt support in
> i40e PF and VF
> 
> Cunming Liang (11):
>   eal/linux: vfio map misc intr to vector zero
>   ixgbe: reserve intr vector zero for misc cause
>   igb: reserve intr vector zero for misc cause
>   eal/linux: not allow to enable zero intr efd
>   eal/linux: add intr api to report multi-vector capability
>   ixgbe: fix rx intr compatible issue with PF mbox
>   ixgbevf: cleanup unnecessary interrupt handler
>   igb: fix rx intr compatible issue with PF mbox
>   i40e: add rx interrupt support
>   i40evf: add rx interrupt support
>   doc: release note update for intr mode
> 
>  doc/guides/rel_notes/release_2_2.rst               |   4 +
>  drivers/net/e1000/igb_ethdev.c                     |  63 +++-
>  drivers/net/i40e/i40e_ethdev.c                     | 374
> +++++++++++++++++----
>  drivers/net/i40e/i40e_ethdev.h                     |  17 +
>  drivers/net/i40e/i40e_ethdev_vf.c                  | 143 +++++++-
>  drivers/net/i40e/i40e_pf.c                         |   7 +-
>  drivers/net/ixgbe/ixgbe_ethdev.c                   | 144 +++-----
>  .../bsdapp/eal/include/exec-env/rte_interrupts.h   |   3 +-
>  lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  35 +-
>  .../linuxapp/eal/include/exec-env/rte_interrupts.h |  16 +-
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   7 +
>  11 files changed, 612 insertions(+), 201 deletions(-)
> 
> --
> 2.4.3
Acked-by: Helin Zhang <helin.zhang@intel.com>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
  2015-10-30  7:11     ` He, Shaopeng
  2015-10-30  7:33     ` Zhang, Helin
@ 2015-10-30 14:22     ` Liang, Cunming
  2015-11-02 15:53     ` David Marchand
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
  4 siblings, 0 replies; 79+ messages in thread
From: Liang, Cunming @ 2015-10-30 14:22 UTC (permalink / raw)
  To: David Marchand (david.marchand@6wind.com); +Cc: dev

Hi David,

May I ask your help to review the patch related to eal ?

Thanks,
Steve
> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, October 30, 2015 1:28 PM
> To: dev@dpdk.org
> Cc: Zhang, Helin; He, Shaopeng; Wu, Jingjing; Liang, Cunming
> Subject: [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
> 
> During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
> The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e,
> fm10k).
> The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the first
> vector to misc interrupt.
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> ---
>  lib/librte_eal/linuxapp/eal/eal_interrupts.c           | 18
> ++++++++++++------
>  .../linuxapp/eal/include/exec-env/rte_interrupts.h     |  3 +++
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
> b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
> index 078318c..8e76a7a 100644
> --- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
> +++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
> @@ -300,8 +300,10 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle)
> {
>  	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
>  	irq_set->start = 0;
>  	fd_ptr = (int *) &irq_set->data;
> -	memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
> -	fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
> +	fd_ptr[MISC_VEC_ID] = intr_handle->fd;
> +	/* follow up with misc(0) interrupt */
> +	memcpy(&fd_ptr[RX_VEC_START], intr_handle->efds,
> +		sizeof(*intr_handle->efds) * intr_handle->nb_efd);
> 
>  	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
> 
> @@ -1068,10 +1070,13 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
> int epfd,
>  	struct rte_epoll_event *rev;
>  	struct rte_epoll_data *epdata;
>  	int epfd_op;
> +	unsigned int efd_idx;
>  	int rc = 0;
> 
> +	efd_idx = (vec >= RX_VEC_START) ? (vec - RX_VEC_START) : vec;
> +
>  	if (!intr_handle || intr_handle->nb_efd == 0 ||
> -	    vec >= intr_handle->nb_efd) {
> +	    efd_idx >= intr_handle->nb_efd) {
>  		RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
>  		return -EPERM;
>  	}
> @@ -1079,7 +1084,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
> int epfd,
>  	switch (op) {
>  	case RTE_INTR_EVENT_ADD:
>  		epfd_op = EPOLL_CTL_ADD;
> -		rev = &intr_handle->elist[vec];
> +		rev = &intr_handle->elist[efd_idx];
>  		if (rev->status != RTE_EPOLL_INVALID) {
>  			RTE_LOG(INFO, EAL, "Event already been added.\n");
>  			return -EEXIST;
> @@ -1091,7 +1096,8 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
> int epfd,
>  		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);
> +		rc = rte_epoll_ctl(epfd, epfd_op,
> +				   intr_handle->efds[efd_idx], rev);
>  		if (!rc)
>  			RTE_LOG(DEBUG, EAL,
>  				"efd %d associated with vec %d added on epfd %d"
> @@ -1101,7 +1107,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
> int epfd,
>  		break;
>  	case RTE_INTR_EVENT_DEL:
>  		epfd_op = EPOLL_CTL_DEL;
> -		rev = &intr_handle->elist[vec];
> +		rev = &intr_handle->elist[efd_idx];
>  		if (rev->status == RTE_EPOLL_INVALID) {
>  			RTE_LOG(INFO, EAL, "Event does not exist.\n");
>  			return -EPERM;
> 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 45071b7..b8fd318 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
> @@ -77,6 +77,9 @@ struct rte_epoll_event {
>  	struct rte_epoll_data epdata;
>  };
> 
> +#define MISC_VEC_ID                (0)
> +#define RX_VEC_START               (MISC_VEC_ID + 1)
> +
>  /** Handle for interrupts. */
>  struct rte_intr_handle {
>  	union {
> --
> 2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
                       ` (2 preceding siblings ...)
  2015-10-30 14:22     ` Liang, Cunming
@ 2015-11-02 15:53     ` David Marchand
  2015-11-04  1:17       ` Liang, Cunming
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
  4 siblings, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 15:53 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

Hello,

On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
wrote:
[snip]

> 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 45071b7..b8fd318 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
> @@ -77,6 +77,9 @@ struct rte_epoll_event {
>         struct rte_epoll_data epdata;
>  };
>
> +#define MISC_VEC_ID                (0)
>

"misc" is not really descriptive ...


> +#define RX_VEC_START               (MISC_VEC_ID + 1)
> +
>

Please, prefix these macros properly.
Else, when looking at the driver code, this kind of macros seems to be
local to the driver.


-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
  2015-10-30  7:13     ` He, Shaopeng
@ 2015-11-02 15:59     ` David Marchand
  2015-11-04  1:21       ` Liang, Cunming
  1 sibling, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 15:59 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it
> in the future.
> Device drivers need to be aware of the capability.
> It's better to avoid condition check on interrupt type(VFIO) everywhere,
> instead
> a capability api is more flexible for the condition change.
>
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> ---
>  lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9
> +++++++++
>  lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10
> ++++++++++
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
>  3 files changed, 26 insertions(+)
>
>
BSD has wrappers for the rest of this api, please add one for this too.


-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-11-02 16:03   ` David Marchand
  2015-11-02 16:09     ` Ananyev, Konstantin
  0 siblings, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 16:03 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Thu, Sep 24, 2015 at 7:33 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start
> normally.
> And PF sometimes won't 'dev_start', so the mbox interrupt register during
> 'dev_init' is required.
>

Can you describe the cases/situations where you would want a device to
handle interrupts while not started ?


Thanks.
-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
@ 2015-11-02 16:06     ` David Marchand
  2015-11-04  1:37       ` Liang, Cunming
  0 siblings, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 16:06 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> As ixgbe vf doesn't support lsc, the patch removes those unused code.
> In addition, it does some tiny cleanup.
>

Please, can you describe this tiny cleanup ?
Did it trigger some bug ?


> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 366923f..794171c 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> [snip]
> @@ -3492,11 +3442,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
>         ixgbevf_dev_rxtx_start(dev);
>
>         /* check and configure queue intr-vector mapping */
> -       if (dev->data->dev_conf.intr_conf.rxq != 0)
> +       if (dev->data->dev_conf.intr_conf.rxq != 0) {
>                 intr_vector = dev->data->nb_rx_queues;
> -
> -       if (rte_intr_efd_enable(intr_handle, intr_vector))
> -               return -1;
> +               if (rte_intr_efd_enable(intr_handle, intr_vector))
> +                       return -1;
> +       }
>
>


-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-02 16:03   ` David Marchand
@ 2015-11-02 16:09     ` Ananyev, Konstantin
  2015-11-02 16:22       ` David Marchand
  0 siblings, 1 reply; 79+ messages in thread
From: Ananyev, Konstantin @ 2015-11-02 16:09 UTC (permalink / raw)
  To: David Marchand, Liang, Cunming; +Cc: dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Marchand
> Sent: Monday, November 02, 2015 4:03 PM
> To: Liang, Cunming
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
> 
> On Thu, Sep 24, 2015 at 7:33 AM, Cunming Liang <cunming.liang@intel.com>
> wrote:
> 
> > When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start
> > normally.
> > And PF sometimes won't 'dev_start', so the mbox interrupt register during
> > 'dev_init' is required.
> >
> 
> Can you describe the cases/situations where you would want a device to
> handle interrupts while not started ?

When PF and VF are both controlled by DPDK process(es).
And user doesn't really want to do any RX/TX through PF - uses PF just to control/configure VF(s). 

> 
> 
> Thanks.
> --
> David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-02 16:09     ` Ananyev, Konstantin
@ 2015-11-02 16:22       ` David Marchand
       [not found]         ` <2601191342CEEE43887BDE71AB97725836AB862D@irsmsx105.ger.corp.intel.com>
  0 siblings, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 16:22 UTC (permalink / raw)
  To: Ananyev, Konstantin; +Cc: dev

On Mon, Nov 2, 2015 at 5:09 PM, Ananyev, Konstantin <
konstantin.ananyev@intel.com> wrote:

>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Marchand
> > Sent: Monday, November 02, 2015 4:03 PM
> > To: Liang, Cunming
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible
> issue with PF mbox
> >
> > On Thu, Sep 24, 2015 at 7:33 AM, Cunming Liang <cunming.liang@intel.com>
> > wrote:
> >
> > > When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF
> start
> > > normally.
> > > And PF sometimes won't 'dev_start', so the mbox interrupt register
> during
> > > 'dev_init' is required.
> > >
> >
> > Can you describe the cases/situations where you would want a device to
> > handle interrupts while not started ?
>
> When PF and VF are both controlled by DPDK process(es).
> And user doesn't really want to do any RX/TX through PF - uses PF just to
> control/configure VF(s).
>
>
Ok, but the user still needs to whitelist the PF (or ensure the PF is not
blacklisted) in one of these processes.
Then, the application would do a "partial" initialisation ?
If you don't want rx/tx, don't poll the port.

Anyway, this is your code :-)


-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
       [not found]         ` <2601191342CEEE43887BDE71AB97725836AB862D@irsmsx105.ger.corp.intel.com>
@ 2015-11-02 16:41           ` Ananyev, Konstantin
  2015-11-02 17:06             ` David Marchand
  0 siblings, 1 reply; 79+ messages in thread
From: Ananyev, Konstantin @ 2015-11-02 16:41 UTC (permalink / raw)
  To: David Marchand (david.marchand@6wind.com); +Cc: dev



 
> 
> From: David Marchand [mailto:david.marchand@6wind.com]
> Sent: Monday, November 02, 2015 4:22 PM
> To: Ananyev, Konstantin
> Cc: Liang, Cunming; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
> 
> On Mon, Nov 2, 2015 at 5:09 PM, Ananyev, Konstantin <konstantin.ananyev@intel.com> wrote:
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Marchand
> > Sent: Monday, November 02, 2015 4:03 PM
> > To: Liang, Cunming
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
> >
> > On Thu, Sep 24, 2015 at 7:33 AM, Cunming Liang <cunming.liang@intel.com>
> > wrote:
> >
> > > When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start
> > > normally.
> > > And PF sometimes won't 'dev_start', so the mbox interrupt register during
> > > 'dev_init' is required.
> > >
> >
> > Can you describe the cases/situations where you would want a device to
> > handle interrupts while not started ?
> 
> When PF and VF are both controlled by DPDK process(es).
> And user doesn't really want to do any RX/TX through PF - uses PF just to control/configure VF(s).
> 
> Ok, but the user still needs to whitelist the PF (or ensure the PF is not blacklisted) in one of these processes.

Yes, at least dev_init() need to be called for that device. 

> Then, the application would do a "partial" initialisation ?

Yep, sort of.

> If you don't want rx/tx, don't poll the port.

Well, the question is why to add an extra restriction here?
Probably user deliberately doesn't want to call dev_start() for PF device -
as he doesn't plan to use it for RX/TX.
Or might be dev_stop() was called just to do some re-configuration 
(allow to TX scattered packets on the PF queues or so).
Or dev_start() for PF has not yet been called.
Why VF should stop working properly because of that? 
Konstantin

> Anyway, this is your code :-)
> 
> 
> --
> David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-02 16:41           ` Ananyev, Konstantin
@ 2015-11-02 17:06             ` David Marchand
  2015-11-02 17:23               ` Ananyev, Konstantin
  0 siblings, 1 reply; 79+ messages in thread
From: David Marchand @ 2015-11-02 17:06 UTC (permalink / raw)
  To: Ananyev, Konstantin; +Cc: dev

On Mon, Nov 2, 2015 at 5:41 PM, Ananyev, Konstantin <
konstantin.ananyev@intel.com> wrote:

> > If you don't want rx/tx, don't poll the port.
>
> Well, the question is why to add an extra restriction here?
>

Well, until I start a port, I would expect it to do nothing.

Probably user deliberately doesn't want to call dev_start() for PF device -
> as he doesn't plan to use it for RX/TX.
> Or might be dev_stop() was called just to do some re-configuration
> (allow to TX scattered packets on the PF queues or so).
> Or dev_start() for PF has not yet been called.
> Why VF should stop working properly because of that?
>

Why not.


-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-02 17:06             ` David Marchand
@ 2015-11-02 17:23               ` Ananyev, Konstantin
  2015-11-02 17:45                 ` David Marchand
  0 siblings, 1 reply; 79+ messages in thread
From: Ananyev, Konstantin @ 2015-11-02 17:23 UTC (permalink / raw)
  To: David Marchand; +Cc: dev



>>> If you don't want rx/tx, don't poll the port.

>>Well, the question is why to add an extra restriction here?

>Well, until I start a port, I would expect it to do nothing.

>>Probably user deliberately doesn't want to call dev_start() for PF device -
>>as he doesn't plan to use it for RX/TX.
>>Or might be dev_stop() was called just to do some re-configuration
>>(allow to TX scattered packets on the PF queues or so).
>>Or dev_start() for PF has not yet been called.
>>Why VF should stop working properly because of that?

>Why not.

I thought I explained it above.
Basically it means that you can't stop your PF without forcing to stop all VFs first.
And you can't start any of your VFs without starting PF first.
I think that adds an unnecessary restrictions and limits systems availability quite significantly.
Konstantin 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-02 17:23               ` Ananyev, Konstantin
@ 2015-11-02 17:45                 ` David Marchand
  0 siblings, 0 replies; 79+ messages in thread
From: David Marchand @ 2015-11-02 17:45 UTC (permalink / raw)
  To: Ananyev, Konstantin; +Cc: dev

On Nov 2, 2015 6:23 PM, "Ananyev, Konstantin" <konstantin.ananyev@intel.com>
wrote:
> >>Probably user deliberately doesn't want to call dev_start() for PF
device -
> >>as he doesn't plan to use it for RX/TX.
> >>Or might be dev_stop() was called just to do some re-configuration
> >>(allow to TX scattered packets on the PF queues or so).
> >>Or dev_start() for PF has not yet been called.
> >>Why VF should stop working properly because of that?
>
> >Why not.
>
> I thought I explained it above.

Sorry wrong choice of words with this "Why not".
I agree with you for this case.

-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero
  2015-11-02 15:53     ` David Marchand
@ 2015-11-04  1:17       ` Liang, Cunming
  0 siblings, 0 replies; 79+ messages in thread
From: Liang, Cunming @ 2015-11-04  1:17 UTC (permalink / raw)
  To: David Marchand; +Cc: dev

Hi David,

On 11/2/2015 11:53 PM, David Marchand wrote:
> Hello,
>
> On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
> wrote:
> [snip]
>
>> 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 45071b7..b8fd318 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
>> @@ -77,6 +77,9 @@ struct rte_epoll_event {
>>          struct rte_epoll_data epdata;
>>   };
>>
>> +#define MISC_VEC_ID                (0)
>>
> "misc" is not really descriptive ...
>
>
>> +#define RX_VEC_START               (MISC_VEC_ID + 1)
>> +
>>
> Please, prefix these macros properly.
> Else, when looking at the driver code, this kind of macros seems to be
> local to the driver.
>
>
That makes sense, will fix it in v3. Thanks. /Steve

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability
  2015-11-02 15:59     ` David Marchand
@ 2015-11-04  1:21       ` Liang, Cunming
  0 siblings, 0 replies; 79+ messages in thread
From: Liang, Cunming @ 2015-11-04  1:21 UTC (permalink / raw)
  To: David Marchand; +Cc: dev

Hi David,

On 11/2/2015 11:59 PM, David Marchand wrote:
> On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
> wrote:
>
>> VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it
>> in the future.
>> Device drivers need to be aware of the capability.
>> It's better to avoid condition check on interrupt type(VFIO) everywhere,
>> instead
>> a capability api is more flexible for the condition change.
>>
>> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
>> ---
>>   lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9
>> +++++++++
>>   lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10
>> ++++++++++
>>   lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
>>   3 files changed, 26 insertions(+)
>>
>>
> BSD has wrappers for the rest of this api, please add one for this too.
Yes, you're right. Thanks.
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler
  2015-11-02 16:06     ` David Marchand
@ 2015-11-04  1:37       ` Liang, Cunming
  0 siblings, 0 replies; 79+ messages in thread
From: Liang, Cunming @ 2015-11-04  1:37 UTC (permalink / raw)
  To: David Marchand; +Cc: dev

Hi David,

On 11/3/2015 12:06 AM, David Marchand wrote:
> On Fri, Oct 30, 2015 at 6:27 AM, Cunming Liang <cunming.liang@intel.com>
> wrote:
>
>> As ixgbe vf doesn't support lsc, the patch removes those unused code.
>> In addition, it does some tiny cleanup.
>>
> Please, can you describe this tiny cleanup ?
> Did it trigger some bug ?
It causes confusing to enable/allocate efd with a zero number of vector.
But this piece of code shall be merged in a different patch. Thanks.
>> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
>> b/drivers/net/ixgbe/ixgbe_ethdev.c
>> index 366923f..794171c 100644
>> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
>> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
>> [snip]
>> @@ -3492,11 +3442,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
>>          ixgbevf_dev_rxtx_start(dev);
>>
>>          /* check and configure queue intr-vector mapping */
>> -       if (dev->data->dev_conf.intr_conf.rxq != 0)
>> +       if (dev->data->dev_conf.intr_conf.rxq != 0) {
>>                  intr_vector = dev->data->nb_rx_queues;
>> -
>> -       if (rte_intr_efd_enable(intr_handle, intr_vector))
>> -               return -1;
>> +               if (rte_intr_efd_enable(intr_handle, intr_vector))
>> +                       return -1;
>> +       }
>>
>>
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e
  2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
                       ` (3 preceding siblings ...)
  2015-11-02 15:53     ` David Marchand
@ 2015-11-04  6:07     ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 01/13] eal: vfio map misc intr to vector zero Cunming Liang
                         ` (13 more replies)
  4 siblings, 14 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

v3 change:
  - rename MISC_VEC_ID and RX_VEC_START
  - add bsdapp dummy
  - split cleanup and fix patches
  - merge doc update along with code change

v2 change:
  - rework to depend on one previous patch
    patch http://dpdk.org/dev/patchwork/patch/7504/
  - always set DIS_AUTOMASK_* bit in PF to avoid ENA flag auto-clear

This patch series contains four major parts.

1. always reserve vector zero for misc cause in vfio mapping
2. add api to declare the capability of multiple interrupt vector support
3. fix the rx interrupt compatible issue with mbox in ixgbe/igb IOV-PF
4. add rx interrupt support in i40e PF and VF


Cunming Liang (13):
  eal: vfio map misc intr to vector zero
  ixgbe: reserve intr vector zero for misc cause
  igb: reserve intr vector zero for misc cause
  eal/linux: not allow to enable zero intr efd
  ixgbe: fix efd_enable with zero number
  igb: fix efd_enable with zero number
  eal: add intr api to report multi-vector capability
  ixgbe: fix rx intr compatible issue with PF mbox
  ixgbe: fix unnecessary intr_vec free in dev_close
  ixgbevf: cleanup unnecessary interrupt handler
  igb: fix rx intr compatible issue with PF mbox
  i40e: add rx interrupt support
  i40evf: add rx interrupt support

 doc/guides/rel_notes/release_2_2.rst               |   5 +
 drivers/net/e1000/e1000_ethdev.h                   |   3 +
 drivers/net/e1000/igb_ethdev.c                     |  63 +++-
 drivers/net/i40e/i40e_ethdev.c                     | 379 +++++++++++++++++----
 drivers/net/i40e/i40e_ethdev.h                     |  20 ++
 drivers/net/i40e/i40e_ethdev_vf.c                  | 144 +++++++-
 drivers/net/i40e/i40e_pf.c                         |   7 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                   | 144 +++-----
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   3 +
 lib/librte_eal/bsdapp/eal/eal_interrupts.c         |   7 +
 .../bsdapp/eal/include/exec-env/rte_interrupts.h   |  16 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   7 +
 lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  36 +-
 .../linuxapp/eal/include/exec-env/rte_interrupts.h |  15 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   7 +
 15 files changed, 654 insertions(+), 202 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 01/13] eal: vfio map misc intr to vector zero
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
                         ` (12 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e, fm10k).
The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the first vector to misc interrupt.

v3 changes:
  - rename MISC_VEC_ID to RTE_INTR_VEC_ZERO_OFFSET
  - rename RX_VEC_START to RTE_INTR_VEC_RXTX_OFFSET
  - add macro definition in bsd header file

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 .../bsdapp/eal/include/exec-env/rte_interrupts.h      |  3 +++
 lib/librte_eal/linuxapp/eal/eal_interrupts.c          | 19 +++++++++++++------
 .../linuxapp/eal/include/exec-env/rte_interrupts.h    |  2 ++
 3 files changed, 18 insertions(+), 6 deletions(-)

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 88d4ae1..05bb484 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
@@ -38,6 +38,9 @@
 #ifndef _RTE_BSDAPP_INTERRUPTS_H_
 #define _RTE_BSDAPP_INTERRUPTS_H_
 
+#define RTE_INTR_VEC_ZERO_OFFSET      0
+#define RTE_INTR_VEC_RXTX_OFFSET      1
+
 enum rte_intr_handle_type {
 	RTE_INTR_HANDLE_UNKNOWN = 0,
 	RTE_INTR_HANDLE_UIO,      /**< uio device handle */
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index a4b9506..8758239 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -301,8 +301,10 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {
 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
 	irq_set->start = 0;
 	fd_ptr = (int *) &irq_set->data;
-	memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
-	fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
+	/* INTR vector offset 0 reserve for non-efds mapping */
+	fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] = intr_handle->fd;
+	memcpy(&fd_ptr[RTE_INTR_VEC_RXTX_OFFSET], intr_handle->efds,
+		sizeof(*intr_handle->efds) * intr_handle->nb_efd);
 
 	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
 
@@ -1083,10 +1085,14 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	struct rte_epoll_event *rev;
 	struct rte_epoll_data *epdata;
 	int epfd_op;
+	unsigned int efd_idx;
 	int rc = 0;
 
+	efd_idx = (vec >= RTE_INTR_VEC_RXTX_OFFSET) ?
+		(vec - RTE_INTR_VEC_RXTX_OFFSET) : vec;
+
 	if (!intr_handle || intr_handle->nb_efd == 0 ||
-	    vec >= intr_handle->nb_efd) {
+	    efd_idx >= intr_handle->nb_efd) {
 		RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
 		return -EPERM;
 	}
@@ -1094,7 +1100,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	switch (op) {
 	case RTE_INTR_EVENT_ADD:
 		epfd_op = EPOLL_CTL_ADD;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status != RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event already been added.\n");
 			return -EEXIST;
@@ -1106,7 +1112,8 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		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);
+		rc = rte_epoll_ctl(epfd, epfd_op,
+				   intr_handle->efds[efd_idx], rev);
 		if (!rc)
 			RTE_LOG(DEBUG, EAL,
 				"efd %d associated with vec %d added on epfd %d"
@@ -1116,7 +1123,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		break;
 	case RTE_INTR_EVENT_DEL:
 		epfd_op = EPOLL_CTL_DEL;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status == RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event does not exist.\n");
 			return -EPERM;
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 b095b86..8da81e7 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
@@ -39,6 +39,8 @@
 #define _RTE_LINUXAPP_INTERRUPTS_H_
 
 #define RTE_MAX_RXTX_INTR_VEC_ID     32
+#define RTE_INTR_VEC_ZERO_OFFSET      0
+#define RTE_INTR_VEC_RXTX_OFFSET      1
 
 enum rte_intr_handle_type {
 	RTE_INTR_HANDLE_UNKNOWN = 0,
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 02/13] ixgbe: reserve intr vector zero for misc cause
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 01/13] eal: vfio map misc intr to vector zero Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 03/13] igb: " Cunming Liang
                         ` (11 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

v3 changes:
  - macro renaming according to the EAL change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 22 ++++++++++++++--------
 drivers/net/ixgbe/ixgbe_ethdev.h |  3 +++
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 25966ef..153ba98 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4478,7 +4478,8 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask |= (1 << queue_id);
+	mask |= (1 << IXGBE_MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	rte_intr_enable(&dev->pci_dev->intr_handle);
@@ -4494,7 +4495,8 @@ ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask &= ~(1 << queue_id);
+	mask &= ~(1 << IXGBE_MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	return 0;
@@ -4630,7 +4632,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t q_idx;
-	uint32_t vector_idx = 0;
+	uint32_t vector_idx = IXGBE_MISC_VEC_ID;
 
 	/* won't configure msix register if no mapping is done
 	 * between intr vector and event fd.
@@ -4662,7 +4664,8 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t queue_id, vec = 0;
+	uint32_t queue_id, base = IXGBE_MISC_VEC_ID;
+	uint32_t vec = IXGBE_MISC_VEC_ID;
 	uint32_t mask;
 	uint32_t gpie;
 
@@ -4672,6 +4675,9 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle))
+		vec = base = IXGBE_RX_VEC_START;
+
 	/* setup GPIE for MSI-x mode */
 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 	gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
@@ -4695,23 +4701,23 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 		/* by default, 1:1 mapping */
 		ixgbe_set_ivar_map(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
 		ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-				   intr_handle->max_intr - 1);
+				   IXGBE_MISC_VEC_ID);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ixgbe_set_ivar_map(hw, -1, 1, intr_handle->max_intr - 1);
+		ixgbe_set_ivar_map(hw, -1, 1, IXGBE_MISC_VEC_ID);
 		break;
 	default:
 		break;
 	}
-	IXGBE_WRITE_REG(hw, IXGBE_EITR(queue_id),
+	IXGBE_WRITE_REG(hw, IXGBE_EITR(IXGBE_MISC_VEC_ID),
 			IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF);
 
 	/* set up to autoclear timer, and the vectors */
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 569d678..1856c42 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -123,6 +123,9 @@
 #define IXGBE_VF_IRQ_ENABLE_MASK        3          /* vf irq enable mask */
 #define IXGBE_VF_MAXMSIVECTOR           1
 
+#define IXGBE_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
+#define IXGBE_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
+
 /*
  * Information about the fdir mode.
  */
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 03/13] igb: reserve intr vector zero for misc cause
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 01/13] eal: vfio map misc intr to vector zero Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
                         ` (10 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

v3 change:
  - macro renaming according to the EAL change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/e1000_ethdev.h |  3 +++
 drivers/net/e1000/igb_ethdev.c   | 19 ++++++++++++++-----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 3c6f613..a667a1a 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -132,6 +132,9 @@
 #define	EM_RXD_ALIGN	(E1000_ALIGN / sizeof(struct e1000_rx_desc))
 #define	EM_TXD_ALIGN	(E1000_ALIGN / sizeof(struct e1000_data_desc))
 
+#define E1000_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
+#define E1000_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
 	uint32_t flags;
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index cd7f7c1..1332974 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -4495,7 +4495,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	uint32_t tmpval, regval, intr_mask;
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t vec = 0;
+	uint32_t vec = E1000_MISC_VEC_ID;
+	uint32_t base = E1000_MISC_VEC_ID;
+	uint32_t misc_shift = 0;
+
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	/* won't configure msix register if no mapping is done
@@ -4504,6 +4507,11 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = base = E1000_RX_VEC_START;
+		misc_shift = 1;
+	}
+
 	/* set interrupt vector for other causes */
 	if (hw->mac.type == e1000_82575) {
 		tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -4532,8 +4540,8 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 		E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
 					E1000_GPIE_PBA | E1000_GPIE_EIAME |
 					E1000_GPIE_NSICR);
-
-		intr_mask = (1 << intr_handle->max_intr) - 1;
+		intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+			misc_shift;
 		regval = E1000_READ_REG(hw, E1000_EIAC);
 		E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
 
@@ -4547,14 +4555,15 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	/* use EIAM to auto-mask when MSI-X interrupt
 	 * is asserted, this saves a register write for every interrupt
 	 */
-	intr_mask = (1 << intr_handle->nb_efd) - 1;
+	intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+		misc_shift;
 	regval = E1000_READ_REG(hw, E1000_EIAM);
 	E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
 
 	for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
 		eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 04/13] eal/linux: not allow to enable zero intr efd
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (2 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 03/13] igb: " Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
                         ` (9 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

The patch adds condition check to avoid enable nothing.
In disable state, both max_intr and nb_efd are zero.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 3 ++-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  | 8 +++++++-
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

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 05bb484..3d138bf 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
@@ -85,8 +85,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8758239..8938067 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -45,6 +45,7 @@
 #include <sys/signalfd.h>
 #include <sys/ioctl.h>
 #include <sys/eventfd.h>
+#include <assert.h>
 
 #include <rte_common.h>
 #include <rte_interrupts.h>
@@ -1148,6 +1149,8 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
 	int fd;
 	uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
 
+	assert(nb_efd != 0);
+
 	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) {
 		for (i = 0; i < n; i++) {
 			fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
@@ -1204,5 +1207,8 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 {
-	return !!(intr_handle->max_intr - intr_handle->nb_efd);
+	if (!rte_intr_dp_is_en(intr_handle))
+		return 1;
+	else
+		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
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 8da81e7..b44e69c 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
@@ -176,8 +176,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 05/13] ixgbe: fix efd_enable with zero number
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (3 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 06/13] igb: " Cunming Liang
                         ` (8 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 153ba98..f1a738c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1975,11 +1975,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
@@ -3862,11 +3862,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	ixgbevf_dev_rxtx_start(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 06/13] igb: fix efd_enable with zero number
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (4 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 07/13] eal: add intr api to report multi-vector capability Cunming Liang
                         ` (7 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 1332974..76d2acc 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1122,11 +1122,11 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle)) {
 		intr_handle->intr_vec =
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 07/13] eal: add intr api to report multi-vector capability
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (5 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 06/13] igb: " Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
                         ` (6 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it in the future.
Device drivers need to be aware of the capability.
It's better to avoid condition check on interrupt type(VFIO) everywhere, instead
a capability api is more flexible for the condition change.

v3 change:
  - add new api dummy in bsdapp

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_interrupts.c                    |  7 +++++++
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 10 ++++++++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map                 |  7 +++++++
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9 +++++++++
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10 ++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
 6 files changed, 50 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal_interrupts.c b/lib/librte_eal/bsdapp/eal/eal_interrupts.c
index 51a13fa..836e483 100644
--- a/lib/librte_eal/bsdapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/bsdapp/eal/eal_interrupts.c
@@ -110,3 +110,10 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	RTE_SET_USED(intr_handle);
 	return 1;
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	RTE_SET_USED(intr_handle);
+	return 0;
+}
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 3d138bf..70a7087 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
@@ -122,4 +122,14 @@ int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
  */
 int rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 64fdfb1..8b00761 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -125,3 +125,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8938067..95beb4c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -1212,3 +1212,12 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	else
 		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX)
+		return 1;
+
+	return 0;
+}
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 b44e69c..3dacbff 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
@@ -215,4 +215,14 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 dbb8fa1..cb9f4d6 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -128,3 +128,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 08/13] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (6 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 07/13] eal: add intr api to report multi-vector capability Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
                         ` (5 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

v3 change:
  - add doc update follow on the code change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |  2 ++
 drivers/net/ixgbe/ixgbe_ethdev.c     | 39 ++++++++++++++++++++++++++----------
 2 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index ca8471b..b082fb6 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -152,6 +152,8 @@ Drivers
   hardware transactional memory support, thread scaling did not work,
   due to the global ring that is shared by all cores.
 
+* **ixgbe: Fixed PF rx interrupt compatible issue with mbox.**
+
 Libraries
 ~~~~~~~~~
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index f1a738c..6b075f6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1126,6 +1126,13 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 			eth_dev->data->port_id, pci_dev->id.vendor_id,
 			pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   ixgbe_dev_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
@@ -1975,7 +1982,10 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
 		if (rte_intr_efd_enable(intr_handle, intr_vector))
 			return -1;
@@ -1984,8 +1994,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
-				    dev->data->nb_rx_queues * sizeof(int),
-				    0);
+				    dev->data->nb_rx_queues * sizeof(int), 0);
 		if (intr_handle->intr_vec == NULL) {
 			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
 				     " intr_vec\n", dev->data->nb_rx_queues);
@@ -2072,20 +2081,22 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 skip_link_setup:
 
-	/* check if lsc interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   ixgbe_dev_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			ixgbe_dev_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     ixgbe_dev_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		ixgbe_dev_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -2197,6 +2208,12 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 	memset(filter_info->fivetuple_mask, 0,
 		sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   ixgbe_dev_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 09/13] ixgbe: fix unnecessary intr_vec free in dev_close
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (7 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
                         ` (4 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

The intr_vec is free in dev_stop. It's not necessary to check in dev_close.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 6b075f6..d5556cc 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -3952,7 +3952,6 @@ static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -3964,12 +3963,6 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
 
 	/* reprogram the RAR[0] in case user changed it. */
 	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
-	pci_dev = dev->pci_dev;
-	if (pci_dev->intr_handle.intr_vec) {
-		rte_free(pci_dev->intr_handle.intr_vec);
-		pci_dev->intr_handle.intr_vec = NULL;
-	}
 }
 
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 10/13] ixgbevf: cleanup unnecessary interrupt handler
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (8 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
                         ` (3 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

As ixgbe vf doesn't support lsc, the patch removes those unused code.
In addition, it does some tiny cleanup.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 62 +---------------------------------------
 1 file changed, 1 insertion(+), 61 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index d5556cc..96aeee3 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -208,8 +208,6 @@ static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_conf
 /* For Virtual Function support */
 static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
-static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_start(struct rte_eth_dev *dev);
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
@@ -225,8 +223,6 @@ static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
 static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
-static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,
-					  void *param);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
 static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
@@ -3068,30 +3064,6 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
-{
-	uint32_t eicr;
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct ixgbe_interrupt *intr =
-		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
-	/* clear all cause mask */
-	ixgbevf_intr_disable(hw);
-
-	/* read-on-clear nic registers here */
-	eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
-	PMD_DRV_LOG(INFO, "eicr %x", eicr);
-
-	intr->flags = 0;
-
-	/* set flag for async link update */
-	if (eicr & IXGBE_EICR_LSC)
-		intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
-
-	return 0;
-}
-
 /**
  * It gets and then prints the link status.
  *
@@ -3187,18 +3159,6 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
-{
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	PMD_DRV_LOG(DEBUG, "enable intr immediately");
-	ixgbevf_intr_enable(hw);
-	rte_intr_enable(&dev->pci_dev->intr_handle);
-	return 0;
-}
-
 /**
  * Interrupt handler which shall be registered for alarm callback for delayed
  * handling specific interrupt to wait for the stable nic state. As the
@@ -3261,16 +3221,6 @@ ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 	ixgbe_dev_interrupt_action(dev);
 }
 
-static void
-ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
-			      void *param)
-{
-	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
-	ixgbevf_dev_interrupt_get_status(dev);
-	ixgbevf_dev_interrupt_action(dev);
-}
-
 static int
 ixgbe_dev_led_on(struct rte_eth_dev *dev)
 {
@@ -3897,16 +3847,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	}
 	ixgbevf_configure_msix(dev);
 
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle))
-			rte_intr_callback_register(intr_handle,
-					ixgbevf_dev_interrupt_handler,
-					(void *)dev);
-		else
-			PMD_INIT_LOG(INFO, "lsc won't enable because of"
-				     " no intr multiplex\n");
-	}
-
 	rte_intr_enable(intr_handle);
 
 	/* Re-enable interrupt for VF */
@@ -4659,7 +4599,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 		intr_handle->intr_vec[q_idx] = vector_idx;
 	}
 
-	/* Configure VF Rx queue ivar */
+	/* Configure VF other cause ivar */
 	ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
 }
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 11/13] igb: fix rx intr compatible issue with PF mbox
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (9 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 12/13] i40e: add rx interrupt support Cunming Liang
                         ` (2 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

When igb runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

v3 change:
  - add doc update follow on the code change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |  2 ++
 drivers/net/e1000/igb_ethdev.c       | 38 ++++++++++++++++++++++++++----------
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index b082fb6..38b0612 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -154,6 +154,8 @@ Drivers
 
 * **ixgbe: Fixed PF rx interrupt compatible issue with mbox.**
 
+* **igb: Fixed PF rx interrupt compatible issue with mbox.**
+
 Libraries
 ~~~~~~~~~
 
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 76d2acc..fcb4dfb 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -760,6 +760,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   eth_igb_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	igb_intr_enable(eth_dev);
 
@@ -1122,13 +1129,16 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
 		if (rte_intr_efd_enable(intr_handle, intr_vector))
 			return -1;
 	}
 
-	if (rte_intr_dp_is_en(intr_handle)) {
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
 				    dev->data->nb_rx_queues * sizeof(int), 0);
@@ -1221,20 +1231,22 @@ eth_igb_start(struct rte_eth_dev *dev)
 	}
 	e1000_setup_link(hw);
 
-	/* check if lsc interrupt feature is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   eth_igb_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			eth_igb_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     eth_igb_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		eth_igb_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1327,6 +1339,12 @@ eth_igb_stop(struct rte_eth_dev *dev)
 	}
 	filter_info->twotuple_mask = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   eth_igb_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 12/13] i40e: add rx interrupt support
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (10 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 13/13] i40evf: " Cunming Liang
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e PF non-IOV mode.
Per queue rx interrupt works on vfio, however on uio, all rx queues share one interrupt vector.

v3 change:
    - macro change according the EAL
    - add doc update follow on the code change

v2 change:
    - add write flush
    - always set DIS_AUTOMASK_

i40e: pf macro
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |   1 +
 drivers/net/i40e/i40e_ethdev.c       | 347 ++++++++++++++++++++++++++++++-----
 drivers/net/i40e/i40e_ethdev.h       |   5 +
 drivers/net/i40e/i40e_pf.c           |   2 +
 4 files changed, 306 insertions(+), 49 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 38b0612..154bf29 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -90,6 +90,7 @@ New Features
 
 * **Added port hotplug support to xenvirt.**
 
+* **Added interrupt mode support on i40e.**
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 34acc8c..c7a51d4 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <assert.h>
 
 #include <rte_string_fns.h>
 #include <rte_pci.h>
@@ -343,7 +344,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
 			       bool offset_loaded,
 			       uint64_t *offset,
 			       uint64_t *stat);
-static void i40e_pf_config_irq0(struct i40e_hw *hw);
+static void i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue);
 static void i40e_dev_interrupt_handler(
 		__rte_unused struct rte_intr_handle *handle, void *param);
 static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
@@ -404,7 +405,10 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 					   struct timespec *timestamp);
 static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
-
+static int i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
+					 uint16_t queue_id);
+static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
+					  uint16_t queue_id);
 
 static const struct rte_pci_id pci_id_i40e_map[] = {
 #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -440,6 +444,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.tx_queue_start               = i40e_dev_tx_queue_start,
 	.tx_queue_stop                = i40e_dev_tx_queue_stop,
 	.rx_queue_setup               = i40e_dev_rx_queue_setup,
+	.rx_queue_intr_enable         = i40e_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable        = i40e_dev_rx_queue_intr_disable,
 	.rx_queue_release             = i40e_dev_rx_queue_release,
 	.rx_queue_count               = i40e_dev_rx_queue_count,
 	.rx_descriptor_done           = i40e_dev_rx_descriptor_done,
@@ -875,7 +881,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		i40e_dev_interrupt_handler, (void *)dev);
 
 	/* configure and enable device interrupt */
-	i40e_pf_config_irq0(hw);
+	i40e_pf_config_irq0(hw, TRUE);
 	i40e_pf_enable_irq0(hw);
 
 	/* enable uio intr after callback register */
@@ -1056,6 +1062,8 @@ err:
 void
 i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t msix_vect = vsi->msix_intr;
 	uint16_t i;
@@ -1067,15 +1075,26 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	}
 
 	if (vsi->type != I40E_VSI_SRIOV) {
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), 0);
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-				msix_vect - 1), 0);
+		if (!rte_intr_allow_others(intr_handle)) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       0);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1), 0);
+		}
 	} else {
 		uint32_t reg;
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), 0);
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+			       I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
 	}
 	I40E_WRITE_FLUSH(hw);
 }
@@ -1090,29 +1109,26 @@ i40e_calc_itr_interval(int16_t interval)
 	return (interval/2);
 }
 
-void
-i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+static void
+__vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
+		       int base_queue, int nb_queue)
 {
+	int i;
 	uint32_t val;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
-	uint16_t msix_vect = vsi->msix_intr;
-	int i;
-
-	for (i = 0; i < vsi->nb_qps; i++)
-		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
 
 	/* Bind all RX queues to allocated MSIX interrupt */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < nb_queue; i++) {
 		val = (msix_vect << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
 			I40E_QINT_RQCTL_ITR_INDX_MASK |
-			((vsi->base_queue + i + 1) <<
-			I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+			((base_queue + i + 1) <<
+			 I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
 			(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
 			I40E_QINT_RQCTL_CAUSE_ENA_MASK;
 
-		if (i == vsi->nb_qps - 1)
+		if (i == nb_queue - 1)
 			val |= I40E_QINT_RQCTL_NEXTQ_INDX_MASK;
-		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), val);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(base_queue + i), val);
 	}
 
 	/* Write first RX queue to Link list register as the head element */
@@ -1120,21 +1136,26 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		uint16_t interval =
 			i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
 
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
-						(vsi->base_queue <<
-				I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-			(0x0 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
-
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-						msix_vect - 1), interval);
-
-#ifndef I40E_GLINT_CTL
-#define I40E_GLINT_CTL                     0x0003F800
-#define I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK 0x4
-#endif
-		/* Disable auto-mask on enabling of all none-zero  interrupt */
-		I40E_WRITE_REG(hw, I40E_GLINT_CTL,
-			I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK);
+		if (msix_vect == I40E_MISC_VEC_ID) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       (base_queue <<
+					I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       interval);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       (base_queue <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1),
+				       interval);
+		}
 	} else {
 		uint32_t reg;
 
@@ -1142,34 +1163,134 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (vsi->base_queue <<
-					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
+				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
 				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
 	}
 
 	I40E_WRITE_FLUSH(hw);
 }
 
+void
+i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+{
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_vect = vsi->msix_intr;
+	uint16_t nb_msix = RTE_MIN(vsi->nb_msix, intr_handle->nb_efd);
+	uint16_t queue_idx = 0;
+	int record = 0;
+	uint32_t val;
+	int i;
+
+	for (i = 0; i < vsi->nb_qps; i++) {
+		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0);
+	}
+
+	/* INTENA flag is not auto-cleared for interrupt */
+	val = I40E_READ_REG(hw, I40E_GLINT_CTL);
+	val |= I40E_GLINT_CTL_DIS_AUTOMASK_PF0_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK;
+	I40E_WRITE_REG(hw, I40E_GLINT_CTL, val);
+
+	/* VF bind interrupt */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue, vsi->nb_qps);
+		return;
+	}
+
+	/* PF & VMDq bind interrupt */
+	if (rte_intr_dp_is_en(intr_handle)) {
+		if (vsi->type == I40E_VSI_MAIN) {
+			queue_idx = 0;
+			record = 1;
+		} else if (vsi->type == I40E_VSI_VMDQ2) {
+			struct i40e_vsi *main_vsi =
+				I40E_DEV_PRIVATE_TO_MAIN_VSI(vsi->adapter);
+			queue_idx = vsi->base_queue - main_vsi->nb_qps;
+			record = 1;
+		}
+	}
+
+	for (i = 0; i < vsi->nb_used_qps; i++) {
+		if (nb_msix <= 1) {
+			if (!rte_intr_allow_others(intr_handle))
+				/* allow to share MISC_VEC_ID */
+				msix_vect = I40E_MISC_VEC_ID;
+
+			/* no enough msix_vect, map all to one */
+			__vsi_queues_bind_intr(vsi, msix_vect,
+					       vsi->base_queue + i,
+					       vsi->nb_used_qps - i);
+			for (; !!record && i < vsi->nb_used_qps; i++)
+				intr_handle->intr_vec[queue_idx + i] =
+					msix_vect;
+			break;
+		}
+		/* 1:1 queue/msix_vect mapping */
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue + i, 1);
+		if (!!record)
+			intr_handle->intr_vec[queue_idx + i] = msix_vect;
+
+		msix_vect++;
+		nb_msix--;
+	}
+}
+
 static void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t interval = i40e_calc_itr_interval(\
-			RTE_LIBRTE_I40E_ITR_INTERVAL);
-
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1),
-					I40E_PFINT_DYN_CTLN_INTENA_MASK |
-					I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+		RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr, i;
+
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				I40E_PFINT_DYN_CTLN_INTENA_MASK |
+				I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
 				(0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
-			(interval << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+				(interval <<
+				 I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTL0_INTENA_MASK |
+			       I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_intr, i;
 
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				       0);
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline uint8_t
@@ -1279,6 +1400,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	int ret, i;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t intr_vector = 0;
 
 	hw->adapter_stopped = 0;
 
@@ -1290,6 +1413,29 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		return -EINVAL;
 	}
 
+	rte_intr_disable(intr_handle);
+
+	if (((RTE_ETH_DEV_SRIOV(dev).active &&
+	      rte_intr_cap_multiple(intr_handle)) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int),
+				    0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	/* Initialize VSI */
 	ret = i40e_dev_rxtx_init(pf);
 	if (ret != I40E_SUCCESS) {
@@ -1298,11 +1444,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	}
 
 	/* Map queues with MSIX interrupt */
+	main_vsi->nb_used_qps = dev->data->nb_rx_queues -
+		pf->nb_cfg_vmdq_vsi * RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 	i40e_vsi_queues_bind_intr(main_vsi);
 	i40e_vsi_enable_queues_intr(main_vsi);
 
 	/* Map VMDQ VSI queues with MSIX interrupt */
 	for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
+		pf->vmdq[i].vsi->nb_used_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 		i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi);
 		i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
 	}
@@ -1339,6 +1488,22 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		goto err_up;
 	}
 
+	if (!rte_intr_allow_others(intr_handle)) {
+		rte_intr_callback_unregister(intr_handle,
+					     i40e_dev_interrupt_handler,
+					     (void *)dev);
+		/* configure and enable device interrupt */
+		i40e_pf_config_irq0(hw, FALSE);
+		i40e_pf_enable_irq0(hw);
+
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
+			PMD_INIT_LOG(INFO, "lsc won't enable because of"
+				     " no intr multiplex\n");
+	}
+
+	/* enable uio intr after callback register */
+	rte_intr_enable(intr_handle);
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -1354,6 +1519,7 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	struct i40e_mirror_rule *p_mirror;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	int i;
 
 	/* Disable all queues */
@@ -1385,6 +1551,18 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	}
 	pf->nb_mirror_rule = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   i40e_dev_interrupt_handler,
+					   (void *)dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static void
@@ -3701,15 +3879,30 @@ i40e_vsi_setup(struct i40e_pf *pf,
 		vsi->base_queue = I40E_FDIR_QUEUE_ID;
 
 	/* VF has MSIX interrupt in VF range, don't allocate here */
-	if (type != I40E_VSI_SRIOV) {
+	if (type == I40E_VSI_MAIN) {
+		ret = i40e_res_pool_alloc(&pf->msix_pool,
+					  RTE_MIN(vsi->nb_qps,
+						  RTE_MAX_RXTX_INTR_VEC_ID));
+		if (ret < 0) {
+			PMD_DRV_LOG(ERR, "VSI MAIN %d get heap failed %d",
+				    vsi->seid, ret);
+			goto fail_queue_alloc;
+		}
+		vsi->msix_intr = ret;
+		vsi->nb_msix = RTE_MIN(vsi->nb_qps, RTE_MAX_RXTX_INTR_VEC_ID);
+	} else if (type != I40E_VSI_SRIOV) {
 		ret = i40e_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret);
 			goto fail_queue_alloc;
 		}
 		vsi->msix_intr = ret;
-	} else
+		vsi->nb_msix = 1;
+	} else {
 		vsi->msix_intr = 0;
+		vsi->nb_msix = 0;
+	}
+
 	/* Add VSI */
 	if (type == I40E_VSI_MAIN) {
 		/* For main VSI, no need to add since it's default one */
@@ -4553,7 +4746,7 @@ i40e_pf_enable_irq0(struct i40e_hw *hw)
 }
 
 static void
-i40e_pf_config_irq0(struct i40e_hw *hw)
+i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue)
 {
 	/* read pending request and disable first */
 	i40e_pf_disable_irq0(hw);
@@ -4561,9 +4754,10 @@ i40e_pf_config_irq0(struct i40e_hw *hw)
 	I40E_WRITE_REG(hw, I40E_PFINT_STAT_CTL0,
 		I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK);
 
-	/* Link no queues with irq0 */
-	I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
-		I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+	if (no_queue)
+		/* Link no queues with irq0 */
+		I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+			       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
 }
 
 static void
@@ -8147,6 +8341,7 @@ i40e_dcb_setup(struct rte_eth_dev *dev)
 		PMD_INIT_LOG(ERR, "dcb sw configure fails");
 		return -ENOSYS;
 	}
+
 	return 0;
 }
 
@@ -8186,5 +8381,59 @@ i40e_dev_get_dcb_info(struct rte_eth_dev *dev,
 				dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
 		}
 	}
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr -
+						   I40E_RX_VEC_START),
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr -
+						   I40E_RX_VEC_START),
+			       0);
+	I40E_WRITE_FLUSH(hw);
+
 	return 0;
 }
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index c64f83b..eff3adb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -159,6 +159,9 @@ enum i40e_flxpld_layer_idx {
 	(1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
 	(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
 
+#define I40E_MISC_VEC_ID                RTE_INTR_VEC_ZERO_OFFSET
+#define I40E_RX_VEC_START               RTE_INTR_VEC_RXTX_OFFSET
+
 struct i40e_adapter;
 
 /**
@@ -256,6 +259,7 @@ struct i40e_vsi {
 	uint16_t seid;           /* The seid of VSI itself */
 	uint16_t uplink_seid;    /* The uplink seid of this VSI */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
 	/*
@@ -264,6 +268,7 @@ struct i40e_vsi {
 	 */
 	uint16_t vsi_id;
 	uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
+	uint16_t nb_msix;   /* The max number of msix vector */
 	uint8_t enabled_tc; /* The traffic class enabled */
 	struct i40e_bw_info bw_info; /* VSI bandwidth information */
 };
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 95c960c..c1d58a8 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -554,6 +554,8 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+	vf->vsi->nb_msix = irqmap->num_vectors;
+	vf->vsi->nb_used_qps = vf->vsi->nb_qps;
 
 	/* Don't care how the TX/RX queue mapping with this vector.
 	 * Link all VF RX queues together. Only did mapping work.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v3 13/13] i40evf: add rx interrupt support
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (11 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 12/13] i40e: add rx interrupt support Cunming Liang
@ 2015-11-04  6:07       ` Cunming Liang
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  6:07 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e VF and some necessary change on PF IOV mode to support VF.
On PF side, running in IOV mode via uio won't allow rx interrupt which is exclusive with mbox interrupt
in single vector competition.
On VF side, one single vector is shared for all the rx queues.

v3 changes:
  - macro change according to EAL
  - rebase on patch http://dpdk.org/dev/patchwork/patch/7790

v2 changes:
  - turn on intr only when rxq flag is set
  - rework base on patch http://dpdk.org/dev/patchwork/patch/7504/

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    |  38 +++++-----
 drivers/net/i40e/i40e_ethdev.h    |  15 ++++
 drivers/net/i40e/i40e_ethdev_vf.c | 144 +++++++++++++++++++++++++++++++++++---
 drivers/net/i40e/i40e_pf.c        |   5 --
 4 files changed, 167 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index c7a51d4..1a00f2e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -76,11 +76,6 @@
 /* Maximun number of VSI */
 #define I40E_MAX_NUM_VSIS          (384UL)
 
-/* Default queue interrupt throttling time in microseconds */
-#define I40E_ITR_INDEX_DEFAULT          0
-#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
-#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
-
 #define I40E_PRE_TX_Q_CFG_WAIT_US       10 /* 10 us */
 
 /* Flow control default timer */
@@ -1099,16 +1094,6 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_FLUSH(hw);
 }
 
-static inline uint16_t
-i40e_calc_itr_interval(int16_t interval)
-{
-	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
-		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
-
-	/* Convert to hardware count, as writing each 1 represents 2 us */
-	return (interval/2);
-}
-
 static void
 __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 		       int base_queue, int nb_queue)
@@ -1159,13 +1144,24 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 	} else {
 		uint32_t reg;
 
-		/* num_msix_vectors_vf needs to minus irq0 */
-		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
-			vsi->user_param + (msix_vect - 1);
+		if (msix_vect == I40E_MISC_VEC_ID) {
+			I40E_WRITE_REG(hw,
+				       I40E_VPINT_LNKLST0(vsi->user_param),
+				       (base_queue <<
+					I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+		} else {
+			/* num_msix_vectors_vf needs to minus irq0 */
+			reg = (hw->func_caps.num_msix_vectors_vf - 1) *
+				vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
-				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+				       (base_queue <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+		}
 	}
 
 	I40E_WRITE_FLUSH(hw);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index eff3adb..d281935 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -162,6 +162,11 @@ enum i40e_flxpld_layer_idx {
 #define I40E_MISC_VEC_ID                RTE_INTR_VEC_ZERO_OFFSET
 #define I40E_RX_VEC_START               RTE_INTR_VEC_RXTX_OFFSET
 
+/* Default queue interrupt throttling time in microseconds */
+#define I40E_ITR_INDEX_DEFAULT          0
+#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
+#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
+
 struct i40e_adapter;
 
 /**
@@ -638,6 +643,16 @@ i40e_align_floor(int n)
 	return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n));
 }
 
+static inline uint16_t
+i40e_calc_itr_interval(int16_t interval)
+{
+	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
+		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
+
+	/* Convert to hardware count, as writing each 1 represents 2 us */
+	return (interval / 2);
+}
+
 #define I40E_VALID_FLOW(flow_type) \
 	((flow_type) == RTE_ETH_FLOW_FRAG_IPV4 || \
 	(flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 18ec46e..d9f1dda 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -150,6 +150,10 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
 				      struct rte_eth_rss_conf *rss_conf);
 static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 					struct rte_eth_rss_conf *rss_conf);
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
@@ -201,6 +205,9 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.tx_queue_stop        = i40evf_dev_tx_queue_stop,
 	.rx_queue_setup       = i40e_dev_rx_queue_setup,
 	.rx_queue_release     = i40e_dev_rx_queue_release,
+	.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
+	.rx_descriptor_done   = i40e_dev_rx_descriptor_done,
 	.tx_queue_setup       = i40e_dev_tx_queue_setup,
 	.tx_queue_release     = i40e_dev_tx_queue_release,
 	.reta_update          = i40evf_dev_rss_reta_update,
@@ -741,22 +748,33 @@ i40evf_config_irq_map(struct rte_eth_dev *dev)
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_irq_map_info) + \
 		sizeof(struct i40e_virtchnl_vector_map)];
 	struct i40e_virtchnl_irq_map_info *map_info;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t vector_id;
 	int i, err;
+
+	if (rte_intr_allow_others(intr_handle)) {
+		if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
+		else
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
+	} else {
+		vector_id = I40E_MISC_VEC_ID;
+	}
+
 	map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer;
 	map_info->num_vectors = 1;
 	map_info->vecmap[0].rxitr_idx = I40E_QINT_RQCTL_MSIX_INDX_NOITR;
 	map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id;
 	/* Alway use default dynamic MSIX interrupt */
-	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
-	else
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
-
+	map_info->vecmap[0].vector_id = vector_id;
 	/* Don't map any tx queue */
 	map_info->vecmap[0].txq_map = 0;
 	map_info->vecmap[0].rxq_map = 0;
-	for (i = 0; i < dev->data->nb_rx_queues; i++)
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		map_info->vecmap[0].rxq_map |= 1 << i;
+		if (rte_intr_dp_is_en(intr_handle))
+			intr_handle->intr_vec[i] = vector_id;
+	}
 
 	args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
 	args.in_args = (u8 *)cmd_buffer;
@@ -1669,6 +1687,16 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		/* To support DPDK PF host */
@@ -1681,6 +1709,8 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
 				I40E_VFINT_DYN_CTL01_INTENA_MASK |
 				I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline void
@@ -1688,13 +1718,76 @@ i40evf_disable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		I40E_WRITE_REG(hw,
-			I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
-			0);
+			       I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR
+						    - 1),
+			       0);
+	else
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+
+	I40E_WRITE_FLUSH(hw);
+}
+
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT));
 	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - I40E_RX_VEC_START),
+			       I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+			       I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr - I40E_RX_VEC_START),
+			       0);
+
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
 }
 
 static int
@@ -1702,7 +1795,9 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ether_addr mac_addr;
+	uint32_t intr_vector = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1712,6 +1807,24 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 	vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
 					dev->data->nb_tx_queues);
 
+	/* check and configure queue intr-vector mapping */
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int), 0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	if (i40evf_rx_init(dev) != 0){
 		PMD_DRV_LOG(ERR, "failed to do RX init");
 		return -1;
@@ -1741,6 +1854,10 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 		goto err_mac;
 	}
 
+	/* vf don't allow intr except for rxq intr */
+	if (dev->data->dev_conf.intr_conf.rxq != 0)
+		rte_intr_enable(intr_handle);
+
 	i40evf_enable_queues_intr(dev);
 	return 0;
 
@@ -1753,11 +1870,20 @@ err_queue:
 static void
 i40evf_dev_stop(struct rte_eth_dev *dev)
 {
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
 	PMD_INIT_FUNC_TRACE();
 
-	i40evf_disable_queues_intr(dev);
 	i40evf_stop_queues(dev);
+	i40evf_disable_queues_intr(dev);
 	i40e_dev_clear_queues(dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index c1d58a8..cbf4e5b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -547,11 +547,6 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 		goto send_msg;
 	}
 
-	if (irqmap->vecmap[0].vector_id == 0) {
-		PMD_DRV_LOG(ERR, "DPDK host don't support use IRQ0");
-		ret = I40E_ERR_PARAM;
-		goto send_msg;
-	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
 	vf->vsi->nb_msix = irqmap->num_vectors;
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e
  2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
                         ` (12 preceding siblings ...)
  2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 13/13] i40evf: " Cunming Liang
@ 2015-11-04  8:45       ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero Cunming Liang
                           ` (13 more replies)
  13 siblings, 14 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

v4 change:
  - remove redundancy condition check on PF

v3 changes:
  - rename MISC_VEC_ID and RX_VEC_START
  - add bsdapp dummy
  - split cleanup and fix patches
  - merge doc update along with code change

v2 changes:
  - rework to depend on one previous patch
    patch http://dpdk.org/dev/patchwork/patch/7504/
  - always set DIS_AUTOMASK_* bit in PF to avoid ENA flag auto-clear

This patch series contains four major parts.

1. always reserve vector zero for misc cause in vfio mapping
2. add api to declare the capability of multiple interrupt vector support
3. fix the rx interrupt compatible issue with mbox in ixgbe/igb IOV-PF
4. add rx interrupt support in i40e PF and VF

Cunming Liang (13):
  eal: vfio map misc intr to vector zero
  ixgbe: reserve intr vector zero for misc cause
  igb: reserve intr vector zero for misc cause
  eal/linux: not allow to enable zero intr efd
  ixgbe: fix efd_enable with zero number
  igb: fix efd_enable with zero number
  eal: add intr api to report multi-vector capability
  ixgbe: fix rx intr compatible issue with PF mbox
  ixgbe: fix unnecessary intr_vec free in dev_close
  ixgbevf: cleanup unnecessary interrupt handler
  igb: fix rx intr compatible issue with PF mbox
  i40e: add rx interrupt support
  i40evf: add rx interrupt support

 doc/guides/rel_notes/release_2_2.rst               |   5 +
 drivers/net/e1000/e1000_ethdev.h                   |   3 +
 drivers/net/e1000/igb_ethdev.c                     |  62 +++-
 drivers/net/i40e/i40e_ethdev.c                     | 378 +++++++++++++++++----
 drivers/net/i40e/i40e_ethdev.h                     |  20 ++
 drivers/net/i40e/i40e_ethdev_vf.c                  | 144 +++++++-
 drivers/net/i40e/i40e_pf.c                         |   7 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                   | 143 +++-----
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   3 +
 lib/librte_eal/bsdapp/eal/eal_interrupts.c         |   7 +
 .../bsdapp/eal/include/exec-env/rte_interrupts.h   |  16 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   7 +
 lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  36 +-
 .../linuxapp/eal/include/exec-env/rte_interrupts.h |  15 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   7 +
 15 files changed, 651 insertions(+), 202 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04 13:06           ` David Marchand
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
                           ` (12 subsequent siblings)
  13 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd, misc_fd}.
The vector number of misc is indeterminable which is ugly to some NIC(e.g. i40e, fm10k).
The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve the first vector to misc interrupt.

v3 changes:
  - rename MISC_VEC_ID to RTE_INTR_VEC_ZERO_OFFSET
  - rename RX_VEC_START to RTE_INTR_VEC_RXTX_OFFSET
  - add macro definition in bsd header file

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 .../bsdapp/eal/include/exec-env/rte_interrupts.h      |  3 +++
 lib/librte_eal/linuxapp/eal/eal_interrupts.c          | 19 +++++++++++++------
 .../linuxapp/eal/include/exec-env/rte_interrupts.h    |  2 ++
 3 files changed, 18 insertions(+), 6 deletions(-)

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 88d4ae1..05bb484 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
@@ -38,6 +38,9 @@
 #ifndef _RTE_BSDAPP_INTERRUPTS_H_
 #define _RTE_BSDAPP_INTERRUPTS_H_
 
+#define RTE_INTR_VEC_ZERO_OFFSET      0
+#define RTE_INTR_VEC_RXTX_OFFSET      1
+
 enum rte_intr_handle_type {
 	RTE_INTR_HANDLE_UNKNOWN = 0,
 	RTE_INTR_HANDLE_UIO,      /**< uio device handle */
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index a4b9506..8758239 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -301,8 +301,10 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {
 	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
 	irq_set->start = 0;
 	fd_ptr = (int *) &irq_set->data;
-	memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
-	fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
+	/* INTR vector offset 0 reserve for non-efds mapping */
+	fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] = intr_handle->fd;
+	memcpy(&fd_ptr[RTE_INTR_VEC_RXTX_OFFSET], intr_handle->efds,
+		sizeof(*intr_handle->efds) * intr_handle->nb_efd);
 
 	ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
 
@@ -1083,10 +1085,14 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	struct rte_epoll_event *rev;
 	struct rte_epoll_data *epdata;
 	int epfd_op;
+	unsigned int efd_idx;
 	int rc = 0;
 
+	efd_idx = (vec >= RTE_INTR_VEC_RXTX_OFFSET) ?
+		(vec - RTE_INTR_VEC_RXTX_OFFSET) : vec;
+
 	if (!intr_handle || intr_handle->nb_efd == 0 ||
-	    vec >= intr_handle->nb_efd) {
+	    efd_idx >= intr_handle->nb_efd) {
 		RTE_LOG(ERR, EAL, "Wrong intr vector number.\n");
 		return -EPERM;
 	}
@@ -1094,7 +1100,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 	switch (op) {
 	case RTE_INTR_EVENT_ADD:
 		epfd_op = EPOLL_CTL_ADD;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status != RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event already been added.\n");
 			return -EEXIST;
@@ -1106,7 +1112,8 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		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);
+		rc = rte_epoll_ctl(epfd, epfd_op,
+				   intr_handle->efds[efd_idx], rev);
 		if (!rc)
 			RTE_LOG(DEBUG, EAL,
 				"efd %d associated with vec %d added on epfd %d"
@@ -1116,7 +1123,7 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
 		break;
 	case RTE_INTR_EVENT_DEL:
 		epfd_op = EPOLL_CTL_DEL;
-		rev = &intr_handle->elist[vec];
+		rev = &intr_handle->elist[efd_idx];
 		if (rev->status == RTE_EPOLL_INVALID) {
 			RTE_LOG(INFO, EAL, "Event does not exist.\n");
 			return -EPERM;
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 b095b86..8da81e7 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
@@ -39,6 +39,8 @@
 #define _RTE_LINUXAPP_INTERRUPTS_H_
 
 #define RTE_MAX_RXTX_INTR_VEC_ID     32
+#define RTE_INTR_VEC_ZERO_OFFSET      0
+#define RTE_INTR_VEC_RXTX_OFFSET      1
 
 enum rte_intr_handle_type {
 	RTE_INTR_HANDLE_UNKNOWN = 0,
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 02/13] ixgbe: reserve intr vector zero for misc cause
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 03/13] igb: " Cunming Liang
                           ` (11 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

v3 changes:
  - macro renaming according to the EAL change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 22 ++++++++++++++--------
 drivers/net/ixgbe/ixgbe_ethdev.h |  3 +++
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 25966ef..153ba98 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4478,7 +4478,8 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask |= (1 << queue_id);
+	mask |= (1 << IXGBE_MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	rte_intr_enable(&dev->pci_dev->intr_handle);
@@ -4494,7 +4495,8 @@ ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
-	mask &= ~(1 << queue_id);
+	mask &= ~(1 << IXGBE_MISC_VEC_ID);
+	RTE_SET_USED(queue_id);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
 	return 0;
@@ -4630,7 +4632,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t q_idx;
-	uint32_t vector_idx = 0;
+	uint32_t vector_idx = IXGBE_MISC_VEC_ID;
 
 	/* won't configure msix register if no mapping is done
 	 * between intr vector and event fd.
@@ -4662,7 +4664,8 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t queue_id, vec = 0;
+	uint32_t queue_id, base = IXGBE_MISC_VEC_ID;
+	uint32_t vec = IXGBE_MISC_VEC_ID;
 	uint32_t mask;
 	uint32_t gpie;
 
@@ -4672,6 +4675,9 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle))
+		vec = base = IXGBE_RX_VEC_START;
+
 	/* setup GPIE for MSI-x mode */
 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 	gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
@@ -4695,23 +4701,23 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 		/* by default, 1:1 mapping */
 		ixgbe_set_ivar_map(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
 		ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-				   intr_handle->max_intr - 1);
+				   IXGBE_MISC_VEC_ID);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ixgbe_set_ivar_map(hw, -1, 1, intr_handle->max_intr - 1);
+		ixgbe_set_ivar_map(hw, -1, 1, IXGBE_MISC_VEC_ID);
 		break;
 	default:
 		break;
 	}
-	IXGBE_WRITE_REG(hw, IXGBE_EITR(queue_id),
+	IXGBE_WRITE_REG(hw, IXGBE_EITR(IXGBE_MISC_VEC_ID),
 			IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF);
 
 	/* set up to autoclear timer, and the vectors */
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 569d678..1856c42 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -123,6 +123,9 @@
 #define IXGBE_VF_IRQ_ENABLE_MASK        3          /* vf irq enable mask */
 #define IXGBE_VF_MAXMSIVECTOR           1
 
+#define IXGBE_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
+#define IXGBE_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
+
 /*
  * Information about the fdir mode.
  */
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 03/13] igb: reserve intr vector zero for misc cause
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
                           ` (10 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

According to the VFIO interrupt mapping, the interrupt vector id for rxq starts from RX_VEC_START.
It doesn't impact the UIO cases.

v3 change:
  - macro renaming according to the EAL change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/e1000_ethdev.h |  3 +++
 drivers/net/e1000/igb_ethdev.c   | 19 ++++++++++++++-----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 3c6f613..a667a1a 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -132,6 +132,9 @@
 #define	EM_RXD_ALIGN	(E1000_ALIGN / sizeof(struct e1000_rx_desc))
 #define	EM_TXD_ALIGN	(E1000_ALIGN / sizeof(struct e1000_data_desc))
 
+#define E1000_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
+#define E1000_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
 	uint32_t flags;
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index cd7f7c1..1332974 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -4495,7 +4495,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	uint32_t tmpval, regval, intr_mask;
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t vec = 0;
+	uint32_t vec = E1000_MISC_VEC_ID;
+	uint32_t base = E1000_MISC_VEC_ID;
+	uint32_t misc_shift = 0;
+
 	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
 	/* won't configure msix register if no mapping is done
@@ -4504,6 +4507,11 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = base = E1000_RX_VEC_START;
+		misc_shift = 1;
+	}
+
 	/* set interrupt vector for other causes */
 	if (hw->mac.type == e1000_82575) {
 		tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -4532,8 +4540,8 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 		E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
 					E1000_GPIE_PBA | E1000_GPIE_EIAME |
 					E1000_GPIE_NSICR);
-
-		intr_mask = (1 << intr_handle->max_intr) - 1;
+		intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+			misc_shift;
 		regval = E1000_READ_REG(hw, E1000_EIAC);
 		E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
 
@@ -4547,14 +4555,15 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 	/* use EIAM to auto-mask when MSI-X interrupt
 	 * is asserted, this saves a register write for every interrupt
 	 */
-	intr_mask = (1 << intr_handle->nb_efd) - 1;
+	intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+		misc_shift;
 	regval = E1000_READ_REG(hw, E1000_EIAM);
 	E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
 
 	for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
 		eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
 		intr_handle->intr_vec[queue_id] = vec;
-		if (vec < intr_handle->nb_efd - 1)
+		if (vec < base + intr_handle->nb_efd - 1)
 			vec++;
 	}
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (2 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 03/13] igb: " Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04 13:06           ` David Marchand
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
                           ` (9 subsequent siblings)
  13 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

The patch adds condition check to avoid enable nothing.
In disable state, both max_intr and nb_efd are zero.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 3 ++-
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  | 8 +++++++-
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

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 05bb484..3d138bf 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
@@ -85,8 +85,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8758239..8938067 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -45,6 +45,7 @@
 #include <sys/signalfd.h>
 #include <sys/ioctl.h>
 #include <sys/eventfd.h>
+#include <assert.h>
 
 #include <rte_common.h>
 #include <rte_interrupts.h>
@@ -1148,6 +1149,8 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
 	int fd;
 	uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
 
+	assert(nb_efd != 0);
+
 	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) {
 		for (i = 0; i < n; i++) {
 			fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
@@ -1204,5 +1207,8 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 {
-	return !!(intr_handle->max_intr - intr_handle->nb_efd);
+	if (!rte_intr_dp_is_en(intr_handle))
+		return 1;
+	else
+		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
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 8da81e7..b44e69c 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
@@ -176,8 +176,9 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
  *
  * @param intr_handle
  *   Pointer to the interrupt handle.
- * @param nb_vec
+ * @param nb_efd
  *   Number of interrupt vector trying to enable.
+ *   The value 0 is not allowed.
  * @return
  *   - On success, zero.
  *   - On failure, a negative value.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 05/13] ixgbe: fix efd_enable with zero number
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (3 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 06/13] igb: " Cunming Liang
                           ` (8 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 153ba98..f1a738c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1975,11 +1975,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
@@ -3862,11 +3862,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	ixgbevf_dev_rxtx_start(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 06/13] igb: fix efd_enable with zero number
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (4 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability Cunming Liang
                           ` (7 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 1332974..76d2acc 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1122,11 +1122,11 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
-
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -1;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
 
 	if (rte_intr_dp_is_en(intr_handle)) {
 		intr_handle->intr_vec =
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (5 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 06/13] igb: " Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04 13:07           ` David Marchand
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
                           ` (6 subsequent siblings)
  13 siblings, 1 reply; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it in the future.
Device drivers need to be aware of the capability.
It's better to avoid condition check on interrupt type(VFIO) everywhere, instead
a capability api is more flexible for the condition change.

v3 change:
  - add new api dummy in bsdapp

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_interrupts.c                    |  7 +++++++
 lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h   | 10 ++++++++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map                 |  7 +++++++
 lib/librte_eal/linuxapp/eal/eal_interrupts.c                  |  9 +++++++++
 lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h | 10 ++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map               |  7 +++++++
 6 files changed, 50 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal_interrupts.c b/lib/librte_eal/bsdapp/eal/eal_interrupts.c
index 51a13fa..836e483 100644
--- a/lib/librte_eal/bsdapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/bsdapp/eal/eal_interrupts.c
@@ -110,3 +110,10 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	RTE_SET_USED(intr_handle);
 	return 1;
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	RTE_SET_USED(intr_handle);
+	return 0;
+}
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 3d138bf..70a7087 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
@@ -122,4 +122,14 @@ int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
  */
 int rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 64fdfb1..8b00761 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -125,3 +125,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 8938067..95beb4c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -1212,3 +1212,12 @@ rte_intr_allow_others(struct rte_intr_handle *intr_handle)
 	else
 		return !!(intr_handle->max_intr - intr_handle->nb_efd);
 }
+
+int
+rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
+{
+	if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX)
+		return 1;
+
+	return 0;
+}
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 b44e69c..3dacbff 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
@@ -215,4 +215,14 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle);
 int
 rte_intr_allow_others(struct rte_intr_handle *intr_handle);
 
+/**
+ * The multiple interrupt vector capability of interrupt handle instance.
+ * It returns zero if no multiple interrupt vector support.
+ *
+ * @param intr_handle
+ *   Pointer to the interrupt handle.
+ */
+int
+rte_intr_cap_multiple(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 dbb8fa1..cb9f4d6 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -128,3 +128,10 @@ DPDK_2.1 {
 	rte_memzone_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	global:
+
+	rte_intr_cap_multiple;
+
+} DPDK_2.1;
\ No newline at end of file
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 08/13] ixgbe: fix rx intr compatible issue with PF mbox
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (6 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
                           ` (5 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

When ixgbe runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

v4 change:
  - remove redundancy condition check

v3 change:
  - add doc update follow on the code change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |  2 ++
 drivers/net/ixgbe/ixgbe_ethdev.c     | 38 +++++++++++++++++++++++++-----------
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index ca8471b..b082fb6 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -152,6 +152,8 @@ Drivers
   hardware transactional memory support, thread scaling did not work,
   due to the global ring that is shared by all cores.
 
+* **ixgbe: Fixed PF rx interrupt compatible issue with mbox.**
+
 Libraries
 ~~~~~~~~~
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index f1a738c..c322168 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1126,6 +1126,13 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 			eth_dev->data->port_id, pci_dev->id.vendor_id,
 			pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   ixgbe_dev_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
@@ -1975,7 +1982,9 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	ixgbe_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+	if ((rte_intr_cap_multiple(intr_handle) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
 		if (rte_intr_efd_enable(intr_handle, intr_vector))
 			return -1;
@@ -1984,8 +1993,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
-				    dev->data->nb_rx_queues * sizeof(int),
-				    0);
+				    dev->data->nb_rx_queues * sizeof(int), 0);
 		if (intr_handle->intr_vec == NULL) {
 			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
 				     " intr_vec\n", dev->data->nb_rx_queues);
@@ -2072,20 +2080,22 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 skip_link_setup:
 
-	/* check if lsc interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   ixgbe_dev_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			ixgbe_dev_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     ixgbe_dev_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		ixgbe_dev_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -2197,6 +2207,12 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 	memset(filter_info->fivetuple_mask, 0,
 		sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   ixgbe_dev_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 09/13] ixgbe: fix unnecessary intr_vec free in dev_close
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (7 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
                           ` (4 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

The intr_vec is free in dev_stop. It's not necessary to check in dev_close.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c322168..948a84f 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -3951,7 +3951,6 @@ static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -3963,12 +3962,6 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
 
 	/* reprogram the RAR[0] in case user changed it. */
 	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
-	pci_dev = dev->pci_dev;
-	if (pci_dev->intr_handle.intr_vec) {
-		rte_free(pci_dev->intr_handle.intr_vec);
-		pci_dev->intr_handle.intr_vec = NULL;
-	}
 }
 
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 10/13] ixgbevf: cleanup unnecessary interrupt handler
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (8 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
                           ` (3 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

As ixgbe vf doesn't support lsc, the patch removes those unused code.
In addition, it does some tiny cleanup.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 62 +---------------------------------------
 1 file changed, 1 insertion(+), 61 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 948a84f..c0dbf79 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -208,8 +208,6 @@ static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_conf
 /* For Virtual Function support */
 static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
-static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_start(struct rte_eth_dev *dev);
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
@@ -225,8 +223,6 @@ static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
 static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
-static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,
-					  void *param);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
 static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
@@ -3067,30 +3063,6 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
-{
-	uint32_t eicr;
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct ixgbe_interrupt *intr =
-		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
-	/* clear all cause mask */
-	ixgbevf_intr_disable(hw);
-
-	/* read-on-clear nic registers here */
-	eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
-	PMD_DRV_LOG(INFO, "eicr %x", eicr);
-
-	intr->flags = 0;
-
-	/* set flag for async link update */
-	if (eicr & IXGBE_EICR_LSC)
-		intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
-
-	return 0;
-}
-
 /**
  * It gets and then prints the link status.
  *
@@ -3186,18 +3158,6 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
-{
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	PMD_DRV_LOG(DEBUG, "enable intr immediately");
-	ixgbevf_intr_enable(hw);
-	rte_intr_enable(&dev->pci_dev->intr_handle);
-	return 0;
-}
-
 /**
  * Interrupt handler which shall be registered for alarm callback for delayed
  * handling specific interrupt to wait for the stable nic state. As the
@@ -3260,16 +3220,6 @@ ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 	ixgbe_dev_interrupt_action(dev);
 }
 
-static void
-ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
-			      void *param)
-{
-	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
-	ixgbevf_dev_interrupt_get_status(dev);
-	ixgbevf_dev_interrupt_action(dev);
-}
-
 static int
 ixgbe_dev_led_on(struct rte_eth_dev *dev)
 {
@@ -3896,16 +3846,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	}
 	ixgbevf_configure_msix(dev);
 
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle))
-			rte_intr_callback_register(intr_handle,
-					ixgbevf_dev_interrupt_handler,
-					(void *)dev);
-		else
-			PMD_INIT_LOG(INFO, "lsc won't enable because of"
-				     " no intr multiplex\n");
-	}
-
 	rte_intr_enable(intr_handle);
 
 	/* Re-enable interrupt for VF */
@@ -4658,7 +4598,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 		intr_handle->intr_vec[q_idx] = vector_idx;
 	}
 
-	/* Configure VF Rx queue ivar */
+	/* Configure VF other cause ivar */
 	ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
 }
 
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 11/13] igb: fix rx intr compatible issue with PF mbox
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (9 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 12/13] i40e: add rx interrupt support Cunming Liang
                           ` (2 subsequent siblings)
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

When igb runs as a PF, mbox interrupt is prerequisite to make VF start normally.
And PF sometimes won't 'dev_start', so the mbox interrupt register during 'dev_init' is required.
The patch rolls back the interrupt register for mbox,lsc to the 'dev_init'.
As UIO doesn't support multiple vector, mbox has to occupy the only one.
It adds condition check on 'dev_start', rxq interrupt is not allowed when PF running in IOV mode via UIO.

v4 change:
  - remove redundancy condition check

v3 change:
  - add doc update follow on the code change

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |  2 ++
 drivers/net/e1000/igb_ethdev.c       | 37 ++++++++++++++++++++++++++----------
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index b082fb6..38b0612 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -154,6 +154,8 @@ Drivers
 
 * **ixgbe: Fixed PF rx interrupt compatible issue with mbox.**
 
+* **igb: Fixed PF rx interrupt compatible issue with mbox.**
+
 Libraries
 ~~~~~~~~~
 
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 76d2acc..2cb115c 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -760,6 +760,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
 		     pci_dev->id.device_id);
 
+	rte_intr_callback_register(&pci_dev->intr_handle,
+				   eth_igb_interrupt_handler,
+				   (void *)eth_dev);
+
+	/* enable uio/vfio intr/eventfd mapping */
+	rte_intr_enable(&pci_dev->intr_handle);
+
 	/* enable support intr */
 	igb_intr_enable(eth_dev);
 
@@ -1122,13 +1129,15 @@ eth_igb_start(struct rte_eth_dev *dev)
 	igb_pf_host_configure(dev);
 
 	/* check and configure queue intr-vector mapping */
-	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+	if ((rte_intr_cap_multiple(intr_handle) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
 		intr_vector = dev->data->nb_rx_queues;
 		if (rte_intr_efd_enable(intr_handle, intr_vector))
 			return -1;
 	}
 
-	if (rte_intr_dp_is_en(intr_handle)) {
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
 		intr_handle->intr_vec =
 			rte_zmalloc("intr_vec",
 				    dev->data->nb_rx_queues * sizeof(int), 0);
@@ -1221,20 +1230,22 @@ eth_igb_start(struct rte_eth_dev *dev)
 	}
 	e1000_setup_link(hw);
 
-	/* check if lsc interrupt feature is enabled */
-	if (dev->data->dev_conf.intr_conf.lsc != 0) {
-		if (rte_intr_allow_others(intr_handle)) {
-			rte_intr_callback_register(intr_handle,
-						   eth_igb_interrupt_handler,
-						   (void *)dev);
+	if (rte_intr_allow_others(intr_handle)) {
+		/* check if lsc interrupt is enabled */
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			eth_igb_lsc_interrupt_setup(dev);
-		} else
+	} else {
+		rte_intr_callback_unregister(intr_handle,
+					     eth_igb_interrupt_handler,
+					     (void *)dev);
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			PMD_INIT_LOG(INFO, "lsc won't enable because of"
 				     " no intr multiplex\n");
 	}
 
 	/* check if rxq interrupt is enabled */
-	if (dev->data->dev_conf.intr_conf.rxq != 0)
+	if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+	    rte_intr_dp_is_en(intr_handle))
 		eth_igb_rxq_interrupt_setup(dev);
 
 	/* enable uio/vfio intr/eventfd mapping */
@@ -1327,6 +1338,12 @@ eth_igb_stop(struct rte_eth_dev *dev)
 	}
 	filter_info->twotuple_mask = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   eth_igb_interrupt_handler,
+					   (void *)dev);
+
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
 	if (intr_handle->intr_vec != NULL) {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 12/13] i40e: add rx interrupt support
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (10 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 13/13] i40evf: " Cunming Liang
  2015-11-04 14:29         ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Thomas Monjalon
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e PF non-IOV mode.
Per queue rx interrupt works on vfio, however on uio, all rx queues share one interrupt vector.

v4 change:
  - remove redundancy condition check

v3 change:
  - macro change according the EAL
  - add doc update follow on the code change

v2 change:
  - add write flush
  - always set DIS_AUTOMASK_

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 doc/guides/rel_notes/release_2_2.rst |   1 +
 drivers/net/i40e/i40e_ethdev.c       | 346 ++++++++++++++++++++++++++++++-----
 drivers/net/i40e/i40e_ethdev.h       |   5 +
 drivers/net/i40e/i40e_pf.c           |   2 +
 4 files changed, 305 insertions(+), 49 deletions(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 38b0612..154bf29 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -90,6 +90,7 @@ New Features
 
 * **Added port hotplug support to xenvirt.**
 
+* **Added interrupt mode support on i40e.**
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 34acc8c..3de1c5c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <assert.h>
 
 #include <rte_string_fns.h>
 #include <rte_pci.h>
@@ -343,7 +344,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
 			       bool offset_loaded,
 			       uint64_t *offset,
 			       uint64_t *stat);
-static void i40e_pf_config_irq0(struct i40e_hw *hw);
+static void i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue);
 static void i40e_dev_interrupt_handler(
 		__rte_unused struct rte_intr_handle *handle, void *param);
 static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
@@ -404,7 +405,10 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 					   struct timespec *timestamp);
 static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
-
+static int i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
+					 uint16_t queue_id);
+static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
+					  uint16_t queue_id);
 
 static const struct rte_pci_id pci_id_i40e_map[] = {
 #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -440,6 +444,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.tx_queue_start               = i40e_dev_tx_queue_start,
 	.tx_queue_stop                = i40e_dev_tx_queue_stop,
 	.rx_queue_setup               = i40e_dev_rx_queue_setup,
+	.rx_queue_intr_enable         = i40e_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable        = i40e_dev_rx_queue_intr_disable,
 	.rx_queue_release             = i40e_dev_rx_queue_release,
 	.rx_queue_count               = i40e_dev_rx_queue_count,
 	.rx_descriptor_done           = i40e_dev_rx_descriptor_done,
@@ -875,7 +881,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		i40e_dev_interrupt_handler, (void *)dev);
 
 	/* configure and enable device interrupt */
-	i40e_pf_config_irq0(hw);
+	i40e_pf_config_irq0(hw, TRUE);
 	i40e_pf_enable_irq0(hw);
 
 	/* enable uio intr after callback register */
@@ -1056,6 +1062,8 @@ err:
 void
 i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t msix_vect = vsi->msix_intr;
 	uint16_t i;
@@ -1067,15 +1075,26 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	}
 
 	if (vsi->type != I40E_VSI_SRIOV) {
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), 0);
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-				msix_vect - 1), 0);
+		if (!rte_intr_allow_others(intr_handle)) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       0);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1), 0);
+		}
 	} else {
 		uint32_t reg;
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), 0);
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+			       I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
 	}
 	I40E_WRITE_FLUSH(hw);
 }
@@ -1090,29 +1109,26 @@ i40e_calc_itr_interval(int16_t interval)
 	return (interval/2);
 }
 
-void
-i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+static void
+__vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
+		       int base_queue, int nb_queue)
 {
+	int i;
 	uint32_t val;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
-	uint16_t msix_vect = vsi->msix_intr;
-	int i;
-
-	for (i = 0; i < vsi->nb_qps; i++)
-		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
 
 	/* Bind all RX queues to allocated MSIX interrupt */
-	for (i = 0; i < vsi->nb_qps; i++) {
+	for (i = 0; i < nb_queue; i++) {
 		val = (msix_vect << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
 			I40E_QINT_RQCTL_ITR_INDX_MASK |
-			((vsi->base_queue + i + 1) <<
-			I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+			((base_queue + i + 1) <<
+			 I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
 			(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
 			I40E_QINT_RQCTL_CAUSE_ENA_MASK;
 
-		if (i == vsi->nb_qps - 1)
+		if (i == nb_queue - 1)
 			val |= I40E_QINT_RQCTL_NEXTQ_INDX_MASK;
-		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), val);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(base_queue + i), val);
 	}
 
 	/* Write first RX queue to Link list register as the head element */
@@ -1120,21 +1136,26 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		uint16_t interval =
 			i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
 
-		I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
-						(vsi->base_queue <<
-				I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-			(0x0 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
-
-		I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
-						msix_vect - 1), interval);
-
-#ifndef I40E_GLINT_CTL
-#define I40E_GLINT_CTL                     0x0003F800
-#define I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK 0x4
-#endif
-		/* Disable auto-mask on enabling of all none-zero  interrupt */
-		I40E_WRITE_REG(hw, I40E_GLINT_CTL,
-			I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK);
+		if (msix_vect == I40E_MISC_VEC_ID) {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+				       (base_queue <<
+					I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITR0(I40E_ITR_INDEX_DEFAULT),
+				       interval);
+		} else {
+			I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1),
+				       (base_queue <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw,
+				       I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT,
+						       msix_vect - 1),
+				       interval);
+		}
 	} else {
 		uint32_t reg;
 
@@ -1142,34 +1163,134 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
 			vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (vsi->base_queue <<
-					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
+				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
 				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
 	}
 
 	I40E_WRITE_FLUSH(hw);
 }
 
+void
+i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
+{
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_vect = vsi->msix_intr;
+	uint16_t nb_msix = RTE_MIN(vsi->nb_msix, intr_handle->nb_efd);
+	uint16_t queue_idx = 0;
+	int record = 0;
+	uint32_t val;
+	int i;
+
+	for (i = 0; i < vsi->nb_qps; i++) {
+		I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0);
+		I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0);
+	}
+
+	/* INTENA flag is not auto-cleared for interrupt */
+	val = I40E_READ_REG(hw, I40E_GLINT_CTL);
+	val |= I40E_GLINT_CTL_DIS_AUTOMASK_PF0_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK |
+		I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK;
+	I40E_WRITE_REG(hw, I40E_GLINT_CTL, val);
+
+	/* VF bind interrupt */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue, vsi->nb_qps);
+		return;
+	}
+
+	/* PF & VMDq bind interrupt */
+	if (rte_intr_dp_is_en(intr_handle)) {
+		if (vsi->type == I40E_VSI_MAIN) {
+			queue_idx = 0;
+			record = 1;
+		} else if (vsi->type == I40E_VSI_VMDQ2) {
+			struct i40e_vsi *main_vsi =
+				I40E_DEV_PRIVATE_TO_MAIN_VSI(vsi->adapter);
+			queue_idx = vsi->base_queue - main_vsi->nb_qps;
+			record = 1;
+		}
+	}
+
+	for (i = 0; i < vsi->nb_used_qps; i++) {
+		if (nb_msix <= 1) {
+			if (!rte_intr_allow_others(intr_handle))
+				/* allow to share MISC_VEC_ID */
+				msix_vect = I40E_MISC_VEC_ID;
+
+			/* no enough msix_vect, map all to one */
+			__vsi_queues_bind_intr(vsi, msix_vect,
+					       vsi->base_queue + i,
+					       vsi->nb_used_qps - i);
+			for (; !!record && i < vsi->nb_used_qps; i++)
+				intr_handle->intr_vec[queue_idx + i] =
+					msix_vect;
+			break;
+		}
+		/* 1:1 queue/msix_vect mapping */
+		__vsi_queues_bind_intr(vsi, msix_vect,
+				       vsi->base_queue + i, 1);
+		if (!!record)
+			intr_handle->intr_vec[queue_idx + i] = msix_vect;
+
+		msix_vect++;
+		nb_msix--;
+	}
+}
+
 static void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	uint16_t interval = i40e_calc_itr_interval(\
-			RTE_LIBRTE_I40E_ITR_INTERVAL);
-
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1),
-					I40E_PFINT_DYN_CTLN_INTENA_MASK |
-					I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+		RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr, i;
+
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				I40E_PFINT_DYN_CTLN_INTENA_MASK |
+				I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
 				(0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
-			(interval << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+				(interval <<
+				 I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTL0_INTENA_MASK |
+			       I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
+	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint16_t msix_intr, i;
 
-	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
+	if (rte_intr_allow_others(intr_handle))
+		for (i = 0; i < vsi->nb_msix; i++) {
+			msix_intr = vsi->msix_intr + i;
+			I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(msix_intr - 1),
+				       0);
+		}
+	else
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline uint8_t
@@ -1279,6 +1400,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	int ret, i;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t intr_vector = 0;
 
 	hw->adapter_stopped = 0;
 
@@ -1290,6 +1413,28 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		return -EINVAL;
 	}
 
+	rte_intr_disable(intr_handle);
+
+	if ((rte_intr_cap_multiple(intr_handle) ||
+	     !RTE_ETH_DEV_SRIOV(dev).active) &&
+	    dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int),
+				    0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	/* Initialize VSI */
 	ret = i40e_dev_rxtx_init(pf);
 	if (ret != I40E_SUCCESS) {
@@ -1298,11 +1443,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	}
 
 	/* Map queues with MSIX interrupt */
+	main_vsi->nb_used_qps = dev->data->nb_rx_queues -
+		pf->nb_cfg_vmdq_vsi * RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 	i40e_vsi_queues_bind_intr(main_vsi);
 	i40e_vsi_enable_queues_intr(main_vsi);
 
 	/* Map VMDQ VSI queues with MSIX interrupt */
 	for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
+		pf->vmdq[i].vsi->nb_used_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
 		i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi);
 		i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
 	}
@@ -1339,6 +1487,22 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		goto err_up;
 	}
 
+	if (!rte_intr_allow_others(intr_handle)) {
+		rte_intr_callback_unregister(intr_handle,
+					     i40e_dev_interrupt_handler,
+					     (void *)dev);
+		/* configure and enable device interrupt */
+		i40e_pf_config_irq0(hw, FALSE);
+		i40e_pf_enable_irq0(hw);
+
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
+			PMD_INIT_LOG(INFO, "lsc won't enable because of"
+				     " no intr multiplex\n");
+	}
+
+	/* enable uio intr after callback register */
+	rte_intr_enable(intr_handle);
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -1354,6 +1518,7 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	struct i40e_vsi *main_vsi = pf->main_vsi;
 	struct i40e_mirror_rule *p_mirror;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	int i;
 
 	/* Disable all queues */
@@ -1385,6 +1550,18 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	}
 	pf->nb_mirror_rule = 0;
 
+	if (!rte_intr_allow_others(intr_handle))
+		/* resume to the default handler */
+		rte_intr_callback_register(intr_handle,
+					   i40e_dev_interrupt_handler,
+					   (void *)dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static void
@@ -3701,15 +3878,30 @@ i40e_vsi_setup(struct i40e_pf *pf,
 		vsi->base_queue = I40E_FDIR_QUEUE_ID;
 
 	/* VF has MSIX interrupt in VF range, don't allocate here */
-	if (type != I40E_VSI_SRIOV) {
+	if (type == I40E_VSI_MAIN) {
+		ret = i40e_res_pool_alloc(&pf->msix_pool,
+					  RTE_MIN(vsi->nb_qps,
+						  RTE_MAX_RXTX_INTR_VEC_ID));
+		if (ret < 0) {
+			PMD_DRV_LOG(ERR, "VSI MAIN %d get heap failed %d",
+				    vsi->seid, ret);
+			goto fail_queue_alloc;
+		}
+		vsi->msix_intr = ret;
+		vsi->nb_msix = RTE_MIN(vsi->nb_qps, RTE_MAX_RXTX_INTR_VEC_ID);
+	} else if (type != I40E_VSI_SRIOV) {
 		ret = i40e_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret);
 			goto fail_queue_alloc;
 		}
 		vsi->msix_intr = ret;
-	} else
+		vsi->nb_msix = 1;
+	} else {
 		vsi->msix_intr = 0;
+		vsi->nb_msix = 0;
+	}
+
 	/* Add VSI */
 	if (type == I40E_VSI_MAIN) {
 		/* For main VSI, no need to add since it's default one */
@@ -4553,7 +4745,7 @@ i40e_pf_enable_irq0(struct i40e_hw *hw)
 }
 
 static void
-i40e_pf_config_irq0(struct i40e_hw *hw)
+i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue)
 {
 	/* read pending request and disable first */
 	i40e_pf_disable_irq0(hw);
@@ -4561,9 +4753,10 @@ i40e_pf_config_irq0(struct i40e_hw *hw)
 	I40E_WRITE_REG(hw, I40E_PFINT_STAT_CTL0,
 		I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK);
 
-	/* Link no queues with irq0 */
-	I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
-		I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
+	if (no_queue)
+		/* Link no queues with irq0 */
+		I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
+			       I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK);
 }
 
 static void
@@ -8147,6 +8340,7 @@ i40e_dcb_setup(struct rte_eth_dev *dev)
 		PMD_INIT_LOG(ERR, "dcb sw configure fails");
 		return -ENOSYS;
 	}
+
 	return 0;
 }
 
@@ -8186,5 +8380,59 @@ i40e_dev_get_dcb_info(struct rte_eth_dev *dev,
 				dcb_info->tc_queue.tc_rxq[0][i].nb_queue;
 		}
 	}
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0,
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr -
+						   I40E_RX_VEC_START),
+			       I40E_PFINT_DYN_CTLN_INTENA_MASK |
+			       I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
+			       (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_PFINT_DYN_CTLN(msix_intr -
+						   I40E_RX_VEC_START),
+			       0);
+	I40E_WRITE_FLUSH(hw);
+
 	return 0;
 }
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index c64f83b..eff3adb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -159,6 +159,9 @@ enum i40e_flxpld_layer_idx {
 	(1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
 	(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
 
+#define I40E_MISC_VEC_ID                RTE_INTR_VEC_ZERO_OFFSET
+#define I40E_RX_VEC_START               RTE_INTR_VEC_RXTX_OFFSET
+
 struct i40e_adapter;
 
 /**
@@ -256,6 +259,7 @@ struct i40e_vsi {
 	uint16_t seid;           /* The seid of VSI itself */
 	uint16_t uplink_seid;    /* The uplink seid of this VSI */
 	uint16_t nb_qps;         /* Number of queue pairs VSI can occupy */
+	uint16_t nb_used_qps;    /* Number of queue pairs VSI uses */
 	uint16_t max_macaddrs;   /* Maximum number of MAC addresses */
 	uint16_t base_queue;     /* The first queue index of this VSI */
 	/*
@@ -264,6 +268,7 @@ struct i40e_vsi {
 	 */
 	uint16_t vsi_id;
 	uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
+	uint16_t nb_msix;   /* The max number of msix vector */
 	uint8_t enabled_tc; /* The traffic class enabled */
 	struct i40e_bw_info bw_info; /* VSI bandwidth information */
 };
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 95c960c..c1d58a8 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -554,6 +554,8 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+	vf->vsi->nb_msix = irqmap->num_vectors;
+	vf->vsi->nb_used_qps = vf->vsi->nb_qps;
 
 	/* Don't care how the TX/RX queue mapping with this vector.
 	 * Link all VF RX queues together. Only did mapping work.
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [dpdk-dev] [PATCH v4 13/13] i40evf: add rx interrupt support
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (11 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 12/13] i40e: add rx interrupt support Cunming Liang
@ 2015-11-04  8:45         ` Cunming Liang
  2015-11-04 14:29         ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Thomas Monjalon
  13 siblings, 0 replies; 79+ messages in thread
From: Cunming Liang @ 2015-11-04  8:45 UTC (permalink / raw)
  To: dev

The patch enables rx interrupt support on i40e VF and some necessary change on PF IOV mode to support VF.
On PF side, running in IOV mode via uio won't allow rx interrupt which is exclusive with mbox interrupt
in single vector competition.
On VF side, one single vector is shared for all the rx queues.

v3 changes:
  - macro change according to EAL
  - rebase on patch http://dpdk.org/dev/patchwork/patch/7790

v2 changes:
  - turn on intr only when rxq flag is set
  - rework base on patch http://dpdk.org/dev/patchwork/patch/7504/

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    |  38 +++++-----
 drivers/net/i40e/i40e_ethdev.h    |  15 ++++
 drivers/net/i40e/i40e_ethdev_vf.c | 146 +++++++++++++++++++++++++++++++++++---
 drivers/net/i40e/i40e_pf.c        |   5 --
 4 files changed, 169 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3de1c5c..2d1c445 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -76,11 +76,6 @@
 /* Maximun number of VSI */
 #define I40E_MAX_NUM_VSIS          (384UL)
 
-/* Default queue interrupt throttling time in microseconds */
-#define I40E_ITR_INDEX_DEFAULT          0
-#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
-#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
-
 #define I40E_PRE_TX_Q_CFG_WAIT_US       10 /* 10 us */
 
 /* Flow control default timer */
@@ -1099,16 +1094,6 @@ i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_FLUSH(hw);
 }
 
-static inline uint16_t
-i40e_calc_itr_interval(int16_t interval)
-{
-	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
-		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
-
-	/* Convert to hardware count, as writing each 1 represents 2 us */
-	return (interval/2);
-}
-
 static void
 __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 		       int base_queue, int nb_queue)
@@ -1159,13 +1144,24 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 	} else {
 		uint32_t reg;
 
-		/* num_msix_vectors_vf needs to minus irq0 */
-		reg = (hw->func_caps.num_msix_vectors_vf - 1) *
-			vsi->user_param + (msix_vect - 1);
+		if (msix_vect == I40E_MISC_VEC_ID) {
+			I40E_WRITE_REG(hw,
+				       I40E_VPINT_LNKLST0(vsi->user_param),
+				       (base_queue <<
+					I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT));
+		} else {
+			/* num_msix_vectors_vf needs to minus irq0 */
+			reg = (hw->func_caps.num_msix_vectors_vf - 1) *
+				vsi->user_param + (msix_vect - 1);
 
-		I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (base_queue <<
-				I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
-				(0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+			I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg),
+				       (base_queue <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) |
+				       (0x0 <<
+					I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT));
+		}
 	}
 
 	I40E_WRITE_FLUSH(hw);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index eff3adb..d281935 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -162,6 +162,11 @@ enum i40e_flxpld_layer_idx {
 #define I40E_MISC_VEC_ID                RTE_INTR_VEC_ZERO_OFFSET
 #define I40E_RX_VEC_START               RTE_INTR_VEC_RXTX_OFFSET
 
+/* Default queue interrupt throttling time in microseconds */
+#define I40E_ITR_INDEX_DEFAULT          0
+#define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */
+#define I40E_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
+
 struct i40e_adapter;
 
 /**
@@ -638,6 +643,16 @@ i40e_align_floor(int n)
 	return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n));
 }
 
+static inline uint16_t
+i40e_calc_itr_interval(int16_t interval)
+{
+	if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX)
+		interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT;
+
+	/* Convert to hardware count, as writing each 1 represents 2 us */
+	return (interval / 2);
+}
+
 #define I40E_VALID_FLOW(flow_type) \
 	((flow_type) == RTE_ETH_FLOW_FRAG_IPV4 || \
 	(flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 18ec46e..615da8d 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -150,6 +150,10 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
 				      struct rte_eth_rss_conf *rss_conf);
 static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 					struct rte_eth_rss_conf *rss_conf);
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
@@ -201,6 +205,9 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.tx_queue_stop        = i40evf_dev_tx_queue_stop,
 	.rx_queue_setup       = i40e_dev_rx_queue_setup,
 	.rx_queue_release     = i40e_dev_rx_queue_release,
+	.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
+	.rx_descriptor_done   = i40e_dev_rx_descriptor_done,
 	.tx_queue_setup       = i40e_dev_tx_queue_setup,
 	.tx_queue_release     = i40e_dev_tx_queue_release,
 	.reta_update          = i40evf_dev_rss_reta_update,
@@ -741,22 +748,33 @@ i40evf_config_irq_map(struct rte_eth_dev *dev)
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_irq_map_info) + \
 		sizeof(struct i40e_virtchnl_vector_map)];
 	struct i40e_virtchnl_irq_map_info *map_info;
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	uint32_t vector_id;
 	int i, err;
+
+	if (rte_intr_allow_others(intr_handle)) {
+		if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
+		else
+			vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
+	} else {
+		vector_id = I40E_MISC_VEC_ID;
+	}
+
 	map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer;
 	map_info->num_vectors = 1;
 	map_info->vecmap[0].rxitr_idx = I40E_QINT_RQCTL_MSIX_INDX_NOITR;
 	map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id;
 	/* Alway use default dynamic MSIX interrupt */
-	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
-	else
-		map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
-
+	map_info->vecmap[0].vector_id = vector_id;
 	/* Don't map any tx queue */
 	map_info->vecmap[0].txq_map = 0;
 	map_info->vecmap[0].rxq_map = 0;
-	for (i = 0; i < dev->data->nb_rx_queues; i++)
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		map_info->vecmap[0].rxq_map |= 1 << i;
+		if (rte_intr_dp_is_en(intr_handle))
+			intr_handle->intr_vec[i] = vector_id;
+	}
 
 	args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP;
 	args.in_args = (u8 *)cmd_buffer;
@@ -1669,6 +1687,16 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		/* To support DPDK PF host */
@@ -1681,6 +1709,8 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev)
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
 				I40E_VFINT_DYN_CTL01_INTENA_MASK |
 				I40E_VFINT_DYN_CTL01_CLEARPBA_MASK);
+
+	I40E_WRITE_FLUSH(hw);
 }
 
 static inline void
@@ -1688,13 +1718,78 @@ i40evf_disable_queues_intr(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+	if (!rte_intr_allow_others(intr_handle)) {
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+		I40E_WRITE_FLUSH(hw);
+		return;
+	}
 
 	if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
 		I40E_WRITE_REG(hw,
-			I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
-			0);
+			       I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR
+						    - 1),
+			       0);
+	else
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+
+	I40E_WRITE_FLUSH(hw);
+}
+
+static int
+i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t interval =
+		i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
+		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
+			       I40E_VFINT_DYN_CTL01_INTENA_MASK |
+			       I40E_VFINT_DYN_CTL01_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT));
 	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr -
+						    I40E_RX_VEC_START),
+			       I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+			       I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK |
+			       (0 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+			       (interval <<
+				I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT));
+
+	I40E_WRITE_FLUSH(hw);
+
+	rte_intr_enable(&dev->pci_dev->intr_handle);
+
+	return 0;
+}
+
+static int
+i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t msix_intr;
+
+	msix_intr = intr_handle->intr_vec[queue_id];
+	if (msix_intr == I40E_MISC_VEC_ID)
 		I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0);
+	else
+		I40E_WRITE_REG(hw,
+			       I40E_VFINT_DYN_CTLN1(msix_intr -
+						    I40E_RX_VEC_START),
+			       0);
+
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
 }
 
 static int
@@ -1702,7 +1797,9 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 	struct ether_addr mac_addr;
+	uint32_t intr_vector = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1712,6 +1809,24 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 	vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
 					dev->data->nb_tx_queues);
 
+	/* check and configure queue intr-vector mapping */
+	if (dev->data->dev_conf.intr_conf.rxq != 0) {
+		intr_vector = dev->data->nb_rx_queues;
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -1;
+	}
+
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    dev->data->nb_rx_queues * sizeof(int), 0);
+		if (!intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec\n", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
 	if (i40evf_rx_init(dev) != 0){
 		PMD_DRV_LOG(ERR, "failed to do RX init");
 		return -1;
@@ -1741,6 +1856,10 @@ i40evf_dev_start(struct rte_eth_dev *dev)
 		goto err_mac;
 	}
 
+	/* vf don't allow intr except for rxq intr */
+	if (dev->data->dev_conf.intr_conf.rxq != 0)
+		rte_intr_enable(intr_handle);
+
 	i40evf_enable_queues_intr(dev);
 	return 0;
 
@@ -1753,11 +1872,20 @@ err_queue:
 static void
 i40evf_dev_stop(struct rte_eth_dev *dev)
 {
+	struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
 	PMD_INIT_FUNC_TRACE();
 
-	i40evf_disable_queues_intr(dev);
 	i40evf_stop_queues(dev);
+	i40evf_disable_queues_intr(dev);
 	i40e_dev_clear_queues(dev);
+
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index c1d58a8..cbf4e5b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -547,11 +547,6 @@ i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 		goto send_msg;
 	}
 
-	if (irqmap->vecmap[0].vector_id == 0) {
-		PMD_DRV_LOG(ERR, "DPDK host don't support use IRQ0");
-		ret = I40E_ERR_PARAM;
-		goto send_msg;
-	}
 	/* This MSIX intr store the intr in VF range */
 	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
 	vf->vsi->nb_msix = irqmap->num_vectors;
-- 
2.4.3

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero Cunming Liang
@ 2015-11-04 13:06           ` David Marchand
  0 siblings, 0 replies; 79+ messages in thread
From: David Marchand @ 2015-11-04 13:06 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Wed, Nov 4, 2015 at 9:45 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> During VFIO_DEVICE_SET_IRQS, the previous order is {Q0_fd, ... Qn_fd,
> misc_fd}.
> The vector number of misc is indeterminable which is ugly to some NIC(e.g.
> i40e, fm10k).
> The patch adjusts the order in {misc_fd, Q0_fd, ... Qn_fd}, always reserve
> the first vector to misc interrupt.
>
> v3 changes:
>   - rename MISC_VEC_ID to RTE_INTR_VEC_ZERO_OFFSET
>   - rename RX_VEC_START to RTE_INTR_VEC_RXTX_OFFSET
>   - add macro definition in bsd header file
>
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
>

Acked-by: David Marchand <david.marchand@6wind.com>

-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
@ 2015-11-04 13:06           ` David Marchand
  0 siblings, 0 replies; 79+ messages in thread
From: David Marchand @ 2015-11-04 13:06 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Wed, Nov 4, 2015 at 9:45 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> The patch adds condition check to avoid enable nothing.
> In disable state, both max_intr and nb_efd are zero.
>
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
>

Acked-by: David Marchand <david.marchand@6wind.com>

-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability Cunming Liang
@ 2015-11-04 13:07           ` David Marchand
  0 siblings, 0 replies; 79+ messages in thread
From: David Marchand @ 2015-11-04 13:07 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

On Wed, Nov 4, 2015 at 9:45 AM, Cunming Liang <cunming.liang@intel.com>
wrote:

> VFIO allows multiple MSI-X vector, others doesn't, but maybe will allow it
> in the future.
> Device drivers need to be aware of the capability.
> It's better to avoid condition check on interrupt type(VFIO) everywhere,
> instead
> a capability api is more flexible for the condition change.
>
> v3 change:
>   - add new api dummy in bsdapp
>
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
>

Acked-by: David Marchand <david.marchand@6wind.com>

-- 
David Marchand

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e
  2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
                           ` (12 preceding siblings ...)
  2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 13/13] i40evf: " Cunming Liang
@ 2015-11-04 14:29         ` Thomas Monjalon
  13 siblings, 0 replies; 79+ messages in thread
From: Thomas Monjalon @ 2015-11-04 14:29 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

2015-11-04 16:45, Cunming Liang:
> v4 change:
>   - remove redundancy condition check on PF
> 
> v3 changes:
>   - rename MISC_VEC_ID and RX_VEC_START
>   - add bsdapp dummy
>   - split cleanup and fix patches
>   - merge doc update along with code change
> 
> v2 changes:
>   - rework to depend on one previous patch
>     patch http://dpdk.org/dev/patchwork/patch/7504/
>   - always set DIS_AUTOMASK_* bit in PF to avoid ENA flag auto-clear
> 
> This patch series contains four major parts.
> 
> 1. always reserve vector zero for misc cause in vfio mapping
> 2. add api to declare the capability of multiple interrupt vector support
> 3. fix the rx interrupt compatible issue with mbox in ixgbe/igb IOV-PF
> 4. add rx interrupt support in i40e PF and VF

Applied, thanks

^ permalink raw reply	[flat|nested] 79+ messages in thread

end of thread, other threads:[~2015-11-04 14:30 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-24  5:33 [dpdk-dev] [PATCH v1 00/11] interrupt mode for i40e Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 03/11] igb: " Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
2015-11-02 16:03   ` David Marchand
2015-11-02 16:09     ` Ananyev, Konstantin
2015-11-02 16:22       ` David Marchand
     [not found]         ` <2601191342CEEE43887BDE71AB97725836AB862D@irsmsx105.ger.corp.intel.com>
2015-11-02 16:41           ` Ananyev, Konstantin
2015-11-02 17:06             ` David Marchand
2015-11-02 17:23               ` Ananyev, Konstantin
2015-11-02 17:45                 ` David Marchand
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 09/11] i40e: add rx interrupt support Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 10/11] i40evf: " Cunming Liang
2015-09-24  5:33 ` [dpdk-dev] [PATCH v1 11/11] doc: release note update for intr mode Cunming Liang
2015-10-30  5:27 ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Cunming Liang
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 01/11] eal/linux: vfio map misc intr to vector zero Cunming Liang
2015-10-30  7:11     ` He, Shaopeng
2015-10-30  7:33     ` Zhang, Helin
2015-10-30 14:22     ` Liang, Cunming
2015-11-02 15:53     ` David Marchand
2015-11-04  1:17       ` Liang, Cunming
2015-11-04  6:07     ` [dpdk-dev] [PATCH v3 00/13] interrupt mode for i40e Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 01/13] eal: vfio map misc intr to vector zero Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 03/13] igb: " Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 06/13] igb: " Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 07/13] eal: add intr api to report multi-vector capability Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 12/13] i40e: add rx interrupt support Cunming Liang
2015-11-04  6:07       ` [dpdk-dev] [PATCH v3 13/13] i40evf: " Cunming Liang
2015-11-04  8:45       ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 01/13] eal: vfio map misc intr to vector zero Cunming Liang
2015-11-04 13:06           ` David Marchand
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 02/13] ixgbe: reserve intr vector zero for misc cause Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 03/13] igb: " Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 04/13] eal/linux: not allow to enable zero intr efd Cunming Liang
2015-11-04 13:06           ` David Marchand
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 05/13] ixgbe: fix efd_enable with zero number Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 06/13] igb: " Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 07/13] eal: add intr api to report multi-vector capability Cunming Liang
2015-11-04 13:07           ` David Marchand
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 08/13] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 09/13] ixgbe: fix unnecessary intr_vec free in dev_close Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 10/13] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 11/13] igb: fix rx intr compatible issue with PF mbox Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 12/13] i40e: add rx interrupt support Cunming Liang
2015-11-04  8:45         ` [dpdk-dev] [PATCH v4 13/13] i40evf: " Cunming Liang
2015-11-04 14:29         ` [dpdk-dev] [PATCH v4 00/13] interrupt mode for i40e Thomas Monjalon
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 02/11] ixgbe: reserve intr vector zero for misc cause Cunming Liang
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 03/11] igb: " Cunming Liang
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 04/11] eal/linux: not allow to enable zero intr efd Cunming Liang
2015-10-30  7:11     ` He, Shaopeng
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 05/11] eal/linux: add intr api to report multi-vector capability Cunming Liang
2015-10-30  7:13     ` He, Shaopeng
2015-11-02 15:59     ` David Marchand
2015-11-04  1:21       ` Liang, Cunming
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 06/11] ixgbe: fix rx intr compatible issue with PF mbox Cunming Liang
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 07/11] ixgbevf: cleanup unnecessary interrupt handler Cunming Liang
2015-11-02 16:06     ` David Marchand
2015-11-04  1:37       ` Liang, Cunming
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 08/11] igb: fix rx intr compatible issue with PF mbox Cunming Liang
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 09/11] i40e: add rx interrupt support Cunming Liang
2015-10-30  7:33     ` Zhang, Helin
2015-10-30  7:35     ` Wu, Jingjing
2015-10-30  5:27   ` [dpdk-dev] [PATCH v2 10/11] i40evf: " Cunming Liang
2015-10-30  7:36     ` Wu, Jingjing
2015-10-30  7:38     ` Zhang, Helin
2015-10-30  5:27   ` [dpdk-dev] [PATCH 11/11] doc: release note update for intr mode Cunming Liang
2015-10-30  8:21   ` [dpdk-dev] [PATCH v2 00/11] interrupt mode for i40e Zhang, Helin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).