From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 74CAE5A71 for ; Wed, 23 Dec 2015 08:37:26 +0100 (CET) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 22 Dec 2015 23:37:25 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,467,1444719600"; d="scan'208";a="713342313" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga003.jf.intel.com with ESMTP; 22 Dec 2015 23:37:24 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id tBN7bM4Z015528; Wed, 23 Dec 2015 15:37:22 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id tBN7bKh1011874; Wed, 23 Dec 2015 15:37:22 +0800 Received: (from heshaope@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id tBN7bKOp011870; Wed, 23 Dec 2015 15:37:20 +0800 From: Shaopeng He To: dev@dpdk.org Date: Wed, 23 Dec 2015 15:37:09 +0800 Message-Id: <1450856233-11825-3-git-send-email-shaopeng.he@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1450856233-11825-1-git-send-email-shaopeng.he@intel.com> References: <1450693192-14500-1-git-send-email-shaopeng.he@intel.com> <1450856233-11825-1-git-send-email-shaopeng.he@intel.com> Subject: [dpdk-dev] [PATCH v5 2/6] fm10k: setup rx queue interrupts for PF and VF X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Dec 2015 07:37:27 -0000 In interrupt mode, each rx queue can have one interrupt to notify the up layer application when packets are available in that queue. Some queues also can share one interrupt. Currently, fm10k needs one separate interrupt for mailbox. So, only those drivers which support multiple interrupt vectors e.g. vfio-pci can work in fm10k interrupt mode. This patch uses the RXINT/INT_MAP registers to map interrupt causes (rx queue and other events) to vectors, and enable these interrupts through kernel drivers like vfio-pci. v5 changes: - add more clean up when memory allocation fails - split line over 80 characters to 2 lines - update interrupt mode limitation in fm10k.rst v4 change: - update release note inside the patch v3 change: - macro renaming according to the EAL change v2 changes: - split one big patch into three smaller ones - reword some comments and commit messages Signed-off-by: Shaopeng He --- doc/guides/nics/fm10k.rst | 7 +++ doc/guides/rel_notes/release_2_3.rst | 2 + drivers/net/fm10k/fm10k.h | 3 + drivers/net/fm10k/fm10k_ethdev.c | 105 +++++++++++++++++++++++++++++++---- 4 files changed, 106 insertions(+), 11 deletions(-) diff --git a/doc/guides/nics/fm10k.rst b/doc/guides/nics/fm10k.rst index 4206b7f..dc5cb6e 100644 --- a/doc/guides/nics/fm10k.rst +++ b/doc/guides/nics/fm10k.rst @@ -65,3 +65,10 @@ The FM10000 family of NICS support a maximum of a 15K jumbo frame. The value is fixed and cannot be changed. So, even when the ``rxmode.max_rx_pkt_len`` member of ``struct rte_eth_conf`` is set to a value lower than 15364, frames up to 15364 bytes can still reach the host interface. + +Interrupt mode +~~~~~~~~~~~~~~~~~~~~~ + +The FM10000 family of NICS need one separate interrupt for mailbox. So only +drivers which support multiple interrupt vectors e.g. vfio-pci can work +for fm10k interrupt mode. diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst index 99de186..2cb5ebd 100644 --- a/doc/guides/rel_notes/release_2_3.rst +++ b/doc/guides/rel_notes/release_2_3.rst @@ -4,6 +4,8 @@ DPDK Release 2.3 New Features ------------ +* **Added fm10k Rx interrupt support.** + Resolved Issues --------------- diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index e2f677a..770d6ba 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -129,6 +129,9 @@ #define RTE_FM10K_TX_MAX_FREE_BUF_SZ 64 #define RTE_FM10K_DESCS_PER_LOOP 4 +#define FM10K_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET +#define FM10K_RX_VEC_START RTE_INTR_VEC_RXTX_OFFSET + #define FM10K_SIMPLE_TX_FLAG ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ ETH_TXQ_FLAGS_NOOFFLOADS) diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index d39c33b..583335a 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -54,6 +54,8 @@ /* Number of chars per uint32 type */ #define CHARS_PER_UINT32 (sizeof(uint32_t)) #define BIT_MASK_PER_UINT32 ((1 << CHARS_PER_UINT32) - 1) +/* default 1:1 map from queue ID to interrupt vector ID */ +#define Q2V(dev, queue_id) (dev->pci_dev->intr_handle.intr_vec[queue_id]) static void fm10k_close_mbx_service(struct fm10k_hw *hw); static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev); @@ -109,6 +111,8 @@ struct fm10k_xstats_name_off fm10k_hw_stats_tx_q_strings[] = { #define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_MAX_QUEUES_PF * \ (FM10K_NB_RX_Q_XSTATS + FM10K_NB_TX_Q_XSTATS)) +static int +fm10k_dev_rxq_interrupt_setup(struct rte_eth_dev *dev); static void fm10k_mbx_initlock(struct fm10k_hw *hw) @@ -687,6 +691,7 @@ static int fm10k_dev_rx_init(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; int i, ret; struct fm10k_rx_queue *rxq; uint64_t base_addr; @@ -694,10 +699,25 @@ fm10k_dev_rx_init(struct rte_eth_dev *dev) uint32_t rxdctl = FM10K_RXDCTL_WRITE_BACK_MIN_DELAY; uint16_t buf_size; - /* Disable RXINT to avoid possible interrupt */ - for (i = 0; i < hw->mac.max_queues; i++) + /* enable RXINT for interrupt mode */ + i = 0; + if (rte_intr_dp_is_en(intr_handle)) { + for (; i < dev->data->nb_rx_queues; i++) { + FM10K_WRITE_REG(hw, FM10K_RXINT(i), Q2V(dev, i)); + if (hw->mac.type == fm10k_mac_pf) + FM10K_WRITE_REG(hw, FM10K_ITR(Q2V(dev, i)), + FM10K_ITR_AUTOMASK | + FM10K_ITR_MASK_CLEAR); + else + FM10K_WRITE_REG(hw, FM10K_VFITR(Q2V(dev, i)), + FM10K_ITR_AUTOMASK | + FM10K_ITR_MASK_CLEAR); + } + } + /* Disable other RXINT to avoid possible interrupt */ + for (; i < hw->mac.max_queues; i++) FM10K_WRITE_REG(hw, FM10K_RXINT(i), - 3 << FM10K_RXINT_TIMER_SHIFT); + 3 << FM10K_RXINT_TIMER_SHIFT); /* Setup RX queues */ for (i = 0; i < dev->data->nb_rx_queues; ++i) { @@ -1053,6 +1073,9 @@ fm10k_dev_start(struct rte_eth_dev *dev) return diag; } + if (fm10k_dev_rxq_interrupt_setup(dev)) + return -EIO; + diag = fm10k_dev_rx_init(dev); if (diag) { PMD_INIT_LOG(ERR, "RX init failed: %d", diag); @@ -2072,7 +2095,7 @@ fm10k_dev_enable_intr_pf(struct rte_eth_dev *dev) uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; /* Bind all local non-queue interrupt to vector 0 */ - int_map |= 0; + int_map |= FM10K_MISC_VEC_ID; FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); @@ -2103,7 +2126,7 @@ fm10k_dev_disable_intr_pf(struct rte_eth_dev *dev) struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_DISABLE; - int_map |= 0; + int_map |= FM10K_MISC_VEC_ID; FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); @@ -2134,7 +2157,7 @@ fm10k_dev_enable_intr_vf(struct rte_eth_dev *dev) uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; /* Bind all local non-queue interrupt to vector 0 */ - int_map |= 0; + int_map |= FM10K_MISC_VEC_ID; /* Only INT 0 available, other 15 are reserved. */ FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); @@ -2151,7 +2174,7 @@ fm10k_dev_disable_intr_vf(struct rte_eth_dev *dev) struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_DISABLE; - int_map |= 0; + int_map |= FM10K_MISC_VEC_ID; /* Only INT 0 available, other 15 are reserved. */ FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); @@ -2162,6 +2185,66 @@ fm10k_dev_disable_intr_vf(struct rte_eth_dev *dev) } static int +fm10k_dev_rxq_interrupt_setup(struct rte_eth_dev *dev) +{ + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; + uint32_t intr_vector, vec; + uint16_t queue_id; + int result = 0; + + /* fm10k needs one separate interrupt for mailbox, + * so only drivers which support multiple interrupt vectors + * e.g. vfio-pci can work for fm10k interrupt mode + */ + if (!rte_intr_cap_multiple(intr_handle) || + dev->data->dev_conf.intr_conf.rxq == 0) + return result; + + intr_vector = dev->data->nb_rx_queues; + + /* disable interrupt first */ + rte_intr_disable(&dev->pci_dev->intr_handle); + if (hw->mac.type == fm10k_mac_pf) + fm10k_dev_disable_intr_pf(dev); + else + fm10k_dev_disable_intr_vf(dev); + + if (rte_intr_efd_enable(intr_handle, intr_vector)) { + PMD_INIT_LOG(ERR, "Failed to init event fd"); + result = -EIO; + } + + if (rte_intr_dp_is_en(intr_handle) && !result) { + intr_handle->intr_vec = rte_zmalloc("intr_vec", + dev->data->nb_rx_queues * sizeof(int), 0); + if (intr_handle->intr_vec) { + for (queue_id = 0, vec = FM10K_RX_VEC_START; + queue_id < dev->data->nb_rx_queues; + queue_id++) { + intr_handle->intr_vec[queue_id] = vec; + if (vec < intr_handle->nb_efd - 1 + + FM10K_RX_VEC_START) + vec++; + } + } else { + PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" + " intr_vec", dev->data->nb_rx_queues); + rte_intr_efd_disable(intr_handle); + result = -ENOMEM; + } + } + + if (hw->mac.type == fm10k_mac_pf) + fm10k_dev_enable_intr_pf(dev); + else + fm10k_dev_enable_intr_vf(dev); + rte_intr_enable(&dev->pci_dev->intr_handle); + hw->mac.ops.update_int_moderator(hw); + return result; +} + +static int fm10k_dev_handle_fault(struct fm10k_hw *hw, uint32_t eicr) { struct fm10k_fault fault; @@ -2531,7 +2614,7 @@ static int eth_fm10k_dev_init(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); - int diag; + int diag, i; struct fm10k_macvlan_filter_info *macvlan; PMD_INIT_FUNC_TRACE(); @@ -2637,7 +2720,7 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev) fm10k_dev_enable_intr_vf(dev); } - /* Enable uio intr after callback registered */ + /* Enable intr after callback registered */ rte_intr_enable(&(dev->pci_dev->intr_handle)); hw->mac.ops.update_int_moderator(hw); @@ -2645,7 +2728,6 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev) /* Make sure Switch Manager is ready before going forward. */ if (hw->mac.type == fm10k_mac_pf) { int switch_ready = 0; - int i; for (i = 0; i < MAX_QUERY_SWITCH_STATE_TIMES; i++) { fm10k_mbx_lock(hw); @@ -2752,7 +2834,8 @@ static struct eth_driver rte_pmd_fm10k = { .pci_drv = { .name = "rte_pmd_fm10k", .id_table = pci_id_fm10k_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | + RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_fm10k_dev_init, .eth_dev_uninit = eth_fm10k_dev_uninit, -- 1.9.3