From: alvinx.zhang@intel.com
To: dev@dpdk.org
Cc: xiaolong.ye@intel.com
Subject: [dpdk-dev] [PATCH v4 06/11] net/igc: enable Rx queue interrupts
Date: Wed, 15 Apr 2020 16:48:05 +0800 [thread overview]
Message-ID: <20200415084810.20816-7-alvinx.zhang@intel.com> (raw)
In-Reply-To: <20200415084810.20816-1-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>
V4: Modify codes according to comments.
---
doc/guides/nics/features/igc.ini | 1 +
drivers/net/igc/igc_ethdev.c | 171 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 168 insertions(+), 4 deletions(-)
diff --git a/doc/guides/nics/features/igc.ini b/doc/guides/nics/features/igc.ini
index 3a68cad..e0bef82 100644
--- a/doc/guides/nics/features/igc.ini
+++ b/doc/guides/nics/features/igc.ini
@@ -26,6 +26,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 c5b5a3d..becac98 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -209,6 +209,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,
@@ -253,6 +257,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,
};
/*
@@ -617,6 +623,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 |= (uint32_t)(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
@@ -631,20 +687,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 = (1u << IGC_MSIX_OTHER_INTR_VEC);
+ if (dev->data->dev_conf.intr_conf.lsc)
+ intr_mask |= (1u << IGC_MSIX_OTHER_INTR_VEC);
/* enable msix auto-clear */
igc_read_reg_check_set_bits(hw, IGC_EIAC, intr_mask);
@@ -656,6 +724,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);
}
@@ -679,6 +754,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
@@ -798,7 +896,26 @@ 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);
@@ -894,6 +1011,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);
@@ -1164,6 +1286,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:
@@ -1904,6 +2027,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 = 1u << (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 = 1u << (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)
{
--
1.8.3.1
next prev parent reply other threads:[~2020-04-15 8:50 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-13 6:30 [dpdk-dev] [PATCH v3 00/11] igc pmd alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 01/11] net/igc: add igc PMD alvinx.zhang
2020-04-13 15:19 ` Stephen Hemminger
2020-04-15 8:47 ` [dpdk-dev] [PATCH v4 00/11] " alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 01/11] net/igc: add " alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 02/11] net/igc: support device initialization alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 03/11] net/igc: implement device base ops alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 04/11] net/igc: support reception and transmission of packets alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 05/11] net/igc: enable statistics alvinx.zhang
2020-04-15 8:48 ` alvinx.zhang [this message]
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 07/11] net/igc: implement flow control ops alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 08/11] net/igc: implement RSS API alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 09/11] net/igc: implement feature of VLAN alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 10/11] net/igc: implement MAC-loopback mode alvinx.zhang
2020-04-15 8:48 ` [dpdk-dev] [PATCH v4 11/11] net/igc: implement flow API alvinx.zhang
2020-04-15 11:14 ` [dpdk-dev] [PATCH v4 00/11] igc PMD Ferruh Yigit
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 02/11] net/igc: support device initialization alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 03/11] net/igc: implement device base ops alvinx.zhang
2020-04-13 15:23 ` Stephen Hemminger
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 04/11] net/igc: support reception and transmission of packets alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 05/11] net/igc: enable statistics alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 06/11] net/igc: enable Rx queue interrupts alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 07/11] net/igc: implement flow control ops alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 08/11] net/igc: implement RSS API alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 09/11] net/igc: implement feature of VLAN alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 10/11] net/igc: implement MAC-loopback mode alvinx.zhang
2020-04-13 6:30 ` [dpdk-dev] [PATCH v3 11/11] net/igc: implement flow API alvinx.zhang
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=20200415084810.20816-7-alvinx.zhang@intel.com \
--to=alvinx.zhang@intel.com \
--cc=dev@dpdk.org \
--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 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).