All of lore.kernel.org
 help / color / mirror / Atom feed
From: alvinx.zhang@intel.com
To: dev@dpdk.org
Cc: haiyue.wang@intel.com, xiaolong.ye@intel.com,
	qi.z.zhang@intel.com, beilei.xing@intel.com,
	Alvin Zhang <alvinx.zhang@intel.com>
Subject: [dpdk-dev] [PATCH v1 07/15] net/igc: enable Rx queue interrupts
Date: Mon,  9 Mar 2020 16:23:59 +0800	[thread overview]
Message-ID: <1583742247-370386-7-git-send-email-alvinx.zhang@intel.com> (raw)
In-Reply-To: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com>

From: Alvin Zhang <alvinx.zhang@intel.com>

Setup NIC to generate MSI-X interrupts.
Set the IVAR register to map interrupt causes to vectors.
Implement interrupt enable/disable functions.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
---
 doc/guides/nics/features/igc.ini |   1 +
 drivers/net/igc/igc_ethdev.c     | 170 ++++++++++++++++++++++++++++++++++++++-
 drivers/net/igc/igc_ethdev.h     |   2 +-
 3 files changed, 168 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/igc.ini b/doc/guides/nics/features/igc.ini
index 9ba817d..79bfb2d 100644
--- a/doc/guides/nics/features/igc.ini
+++ b/doc/guides/nics/features/igc.ini
@@ -25,6 +25,7 @@ L4 checksum offload  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+Rx interrupt         = Y
 Linux UIO            = Y
 Linux VFIO           = Y
 x86-64               = Y
diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c
index 6f03ad1..0a5d37e 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -203,6 +203,10 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 static int
 eth_igc_queue_stats_mapping_set(struct rte_eth_dev *dev,
 	uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx);
+static int
+eth_igc_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
+static int
+eth_igc_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 static const struct eth_dev_ops eth_igc_ops = {
 	.dev_configure		= eth_igc_configure,
@@ -247,6 +251,8 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	.stats_reset		= eth_igc_xstats_reset,
 	.xstats_reset		= eth_igc_xstats_reset,
 	.queue_stats_mapping_set = eth_igc_queue_stats_mapping_set,
+	.rx_queue_intr_enable	= eth_igc_rx_queue_intr_enable,
+	.rx_queue_intr_disable	= eth_igc_rx_queue_intr_disable,
 };
 
 /*
@@ -612,6 +618,56 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 
 	/* Clean datapath event and queue/vec mapping */
 	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec != NULL) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+}
+
+/*
+ * write interrupt vector allocation register
+ * @hw
+ *  board private structure
+ * @queue_index
+ *  queue index, valid 0,1,2,3
+ * @tx
+ *  tx:1, rx:0
+ * @msix_vector
+ *  msix-vector, valid 0,1,2,3,4
+ */
+static void
+igc_write_ivar(struct igc_hw *hw, uint8_t queue_index,
+		bool tx, uint8_t msix_vector)
+{
+	uint8_t offset = 0;
+	uint8_t reg_index = queue_index >> 1;
+	uint32_t val;
+
+	/*
+	 * IVAR(0)
+	 * bit31...24	bit23...16	bit15...8	bit7...0
+	 * TX1		RX1		TX0		RX0
+	 *
+	 * IVAR(1)
+	 * bit31...24	bit23...16	bit15...8	bit7...0
+	 * TX3		RX3		TX2		RX2
+	 */
+
+	if (tx)
+		offset = 8;
+
+	if (queue_index & 1)
+		offset += 16;
+
+	val = IGC_READ_REG_ARRAY(hw, IGC_IVAR0, reg_index);
+
+	/* clear bits */
+	val &= ~((uint32_t)0xFF << offset);
+
+	/* write vector and valid bit */
+	val |= (msix_vector | IGC_IVAR_VALID) << offset;
+
+	IGC_WRITE_REG_ARRAY(hw, IGC_IVAR0, reg_index, val);
 }
 
 /* Sets up the hardware to generate MSI-X interrupts properly
@@ -626,20 +682,32 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
 	uint32_t intr_mask;
+	uint32_t vec = IGC_MISC_VEC_ID;
+	uint32_t base = IGC_MISC_VEC_ID;
+	uint32_t misc_shift = 0;
+	int i;
 
 	/* won't configure msix register if no mapping is done
 	 * between intr vector and event fd
 	 */
-	if (!rte_intr_dp_is_en(intr_handle) ||
-		!dev->data->dev_conf.intr_conf.lsc)
+	if (!rte_intr_dp_is_en(intr_handle))
 		return;
 
+	if (rte_intr_allow_others(intr_handle)) {
+		base = IGC_RX_VEC_START;
+		vec = base;
+		misc_shift = 1;
+	}
+
 	/* turn on MSI-X capability first */
 	IGC_WRITE_REG(hw, IGC_GPIE, IGC_GPIE_MSIX_MODE |
 				IGC_GPIE_PBA | IGC_GPIE_EIAME |
 				IGC_GPIE_NSICR);
+	intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+		misc_shift;
 
-	intr_mask = (1 << IGC_MSIX_OTHER_INTR_VEC);
+	if (dev->data->dev_conf.intr_conf.lsc)
+		intr_mask |= (1 << IGC_MSIX_OTHER_INTR_VEC);
 
 	/* enable msix auto-clear */
 	igc_read_reg_check_set_bits(hw, IGC_EIAC, intr_mask);
@@ -651,6 +719,13 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	/* enable auto-mask */
 	igc_read_reg_check_set_bits(hw, IGC_EIAM, intr_mask);
 
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		igc_write_ivar(hw, i, 0, vec);
+		intr_handle->intr_vec[i] = vec;
+		if (vec < base + intr_handle->nb_efd - 1)
+			vec++;
+	}
+
 	IGC_WRITE_FLUSH(hw);
 }
 
@@ -674,6 +749,29 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 }
 
 /*
+ * It enables the interrupt.
+ * It will be called once only during nic initialized.
+ */
+static void
+igc_rxq_interrupt_setup(struct rte_eth_dev *dev)
+{
+	uint32_t mask;
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	int misc_shift = rte_intr_allow_others(intr_handle) ? 1 : 0;
+
+	/* won't configure msix register if no mapping is done
+	 * between intr vector and event fd
+	 */
+	if (!rte_intr_dp_is_en(intr_handle))
+		return;
+
+	mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) << misc_shift;
+	IGC_WRITE_REG(hw, IGC_EIMS, mask);
+}
+
+/*
  *  Get hardware rx-buffer size.
  */
 static inline int
@@ -793,7 +891,25 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	}
 	adapter->stopped = 0;
 
-	/* confiugre msix for rx interrupt */
+	/* check and configure queue intr-vector mapping */
+	if (rte_intr_cap_multiple(intr_handle) &&
+		dev->data->dev_conf.intr_conf.rxq) {
+		uint32_t 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 == NULL) {
+			PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues"
+				     " intr_vec", dev->data->nb_rx_queues);
+			return -ENOMEM;
+		}
+	}
+
+	/* configure msix for rx interrupt */
 	igc_configure_msix_intr(dev);
 
 	igc_tx_init(dev);
@@ -889,6 +1005,11 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	rte_eal_alarm_set(IGC_ALARM_INTERVAL,
 			igc_update_queue_stats_handler, dev);
 
+	/* check if rxq interrupt is enabled */
+	if (dev->data->dev_conf.intr_conf.rxq &&
+			rte_intr_dp_is_en(intr_handle))
+		igc_rxq_interrupt_setup(dev);
+
 	/* resume enabled intr since hw reset */
 	igc_intr_other_enable(dev);
 
@@ -1161,6 +1282,7 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 		igc->txq_stats_map[i] = -1;
 		igc->rxq_stats_map[i] = -1;
 	}
+
 	return 0;
 
 err_late:
@@ -1908,6 +2030,46 @@ static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
 }
 
 static int
+eth_igc_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	uint32_t vec = IGC_MISC_VEC_ID;
+
+	if (rte_intr_allow_others(intr_handle))
+		vec = IGC_RX_VEC_START;
+
+	uint32_t mask = 1 << (queue_id + vec);
+
+	IGC_WRITE_REG(hw, IGC_EIMC, mask);
+	IGC_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+static int
+eth_igc_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	uint32_t vec = IGC_MISC_VEC_ID;
+
+	if (rte_intr_allow_others(intr_handle))
+		vec = IGC_RX_VEC_START;
+
+	uint32_t mask = 1 << (queue_id + vec);
+
+	IGC_WRITE_REG(hw, IGC_EIMS, mask);
+	IGC_WRITE_FLUSH(hw);
+
+	rte_intr_enable(intr_handle);
+
+	return 0;
+}
+
+static int
 eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct rte_pci_device *pci_dev)
 {
diff --git a/drivers/net/igc/igc_ethdev.h b/drivers/net/igc/igc_ethdev.h
index 20738df..557aa81 100644
--- a/drivers/net/igc/igc_ethdev.h
+++ b/drivers/net/igc/igc_ethdev.h
@@ -118,7 +118,7 @@ struct igc_adapter {
 	int16_t txq_stats_map[IGC_QUEUE_PAIRS_NUM];
 	int16_t rxq_stats_map[IGC_QUEUE_PAIRS_NUM];
 
-	struct igc_interrupt  intr;
+	struct igc_interrupt	intr;
 	bool		stopped;
 };
 
-- 
1.8.3.1


  parent reply	other threads:[~2020-03-09  8:29 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-09  8:23 [dpdk-dev] [PATCH v1 01/15] net/igc: add igc PMD alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 02/15] net/igc: update base share codes alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 03/15] net/igc: device initialization alvinx.zhang
2020-03-12  4:42   ` Ye Xiaolong
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 04/15] net/igc: implement device base ops alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 05/15] net/igc: support reception and transmission of packets alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 06/15] net/igc: implement status API alvinx.zhang
2020-03-09  8:23 ` alvinx.zhang [this message]
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 08/15] net/igc: implement flow control ops alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 09/15] net/igc: implement RSS API alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 10/15] net/igc: implement feature of VLAN alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 11/15] net/igc: implement ether-type filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 12/15] net/igc: implement 2-tuple filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 13/15] net/igc: implement TCP SYN filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 14/15] net/igc: implement hash filter configure alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 15/15] net/igc: implement flow API alvinx.zhang
2020-03-09  8:35 ` [dpdk-dev] [PATCH v1 01/15] net/igc: add igc PMD Ye Xiaolong
2020-03-12  3:09 ` Ye Xiaolong
2020-03-20  2:46 ` [dpdk-dev] [PATCH v2 00/14] " alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 01/14] net/igc: add " alvinx.zhang
2020-04-03 12:21     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 02/14] net/igc: support device initialization alvinx.zhang
2020-04-03 12:23     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 03/14] net/igc: implement device base ops alvinx.zhang
2020-04-03 12:24     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 04/14] net/igc: support reception and transmission of packets alvinx.zhang
2020-04-03 12:27     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 05/14] net/igc: implement status API alvinx.zhang
2020-04-03 12:24     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 06/14] net/igc: enable Rx queue interrupts alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 07/14] net/igc: implement flow control ops alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 08/14] net/igc: implement RSS API alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 09/14] net/igc: implement feature of VLAN alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 10/14] net/igc: implement ether-type filter alvinx.zhang
2020-04-03 12:26     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 11/14] net/igc: implement 2-tuple filter alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 12/14] net/igc: implement TCP SYN filter alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 13/14] net/igc: implement hash filter configure alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 14/14] net/igc: implement flow API alvinx.zhang
2020-04-03 12:26     ` Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1583742247-370386-7-git-send-email-alvinx.zhang@intel.com \
    --to=alvinx.zhang@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=dev@dpdk.org \
    --cc=haiyue.wang@intel.com \
    --cc=qi.z.zhang@intel.com \
    --cc=xiaolong.ye@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.