From patchwork Fri Aug 1 07:08:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 114 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 34205B370 for ; Fri, 1 Aug 2014 09:06:49 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 01 Aug 2014 00:03:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.01,778,1400050800"; d="scan'208";a="582081512" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga002.jf.intel.com with ESMTP; 01 Aug 2014 00:08:49 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id s7178muV014882; Fri, 1 Aug 2014 15:08:48 +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 s7178ini025033; Fri, 1 Aug 2014 15:08:46 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s7178iVu025029; Fri, 1 Aug 2014 15:08:44 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Fri, 1 Aug 2014 15:08:31 +0800 Message-Id: <1406876916-24869-2-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1406876916-24869-1-git-send-email-jingjing.wu@intel.com> References: <1406876916-24869-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH 1/6] i40e: flow director resource reserve and initialize on i40e 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: Fri, 01 Aug 2014 07:06:50 -0000 flow director resource reserve and initialize on i40e, it includes - queue initialization and switch on and vsi creation during setup - queue vsi for flow director release during close Signed-off-by: jingjing.wu --- lib/librte_pmd_i40e/Makefile | 1 + lib/librte_pmd_i40e/i40e_ethdev.c | 40 +++++++++-- lib/librte_pmd_i40e/i40e_ethdev.h | 22 ++++++- lib/librte_pmd_i40e/i40e_fdir.c | 135 ++++++++++++++++++++++++++++++++++++++ lib/librte_pmd_i40e/i40e_rxtx.c | 127 +++++++++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 lib/librte_pmd_i40e/i40e_fdir.c diff --git a/lib/librte_pmd_i40e/Makefile b/lib/librte_pmd_i40e/Makefile index 4b31675..6537654 100644 --- a/lib/librte_pmd_i40e/Makefile +++ b/lib/librte_pmd_i40e/Makefile @@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c +SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index 9ed31b5..47125c7 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -516,6 +516,7 @@ eth_i40e_dev_init(__rte_unused struct eth_driver *eth_drv, err_setup_pf_switch: rte_free(pf->main_vsi); + i40e_fdir_teardown(pf); err_get_mac_addr: err_configure_lan_hmc: (void)i40e_shutdown_lan_hmc(hw); @@ -728,6 +729,7 @@ i40e_dev_close(struct rte_eth_dev *dev) /* release all the existing VSIs and VEBs */ i40e_vsi_release(pf->main_vsi); + i40e_fdir_teardown(pf); /* shutdown the adminq */ i40e_aq_queue_shutdown(hw, true); @@ -2262,7 +2264,11 @@ i40e_vsi_release(struct i40e_vsi *vsi) TAILQ_FOREACH(f, &vsi->mac_list, next) rte_free(f); - if (vsi->type != I40E_VSI_MAIN) { + /* + * For FDIR vsi, there is not actual HW VSI needed, no need to + * call adminq and removing fromtailq. + */ + if (vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_FDIR) { /* Remove vsi from parent's sibling list */ if (vsi->parent_vsi == NULL || vsi->parent_vsi->veb == NULL) { PMD_DRV_LOG(ERR, "VSI's parent VSI is NULL\n"); @@ -2379,7 +2385,8 @@ i40e_vsi_setup(struct i40e_pf *pf, struct ether_addr broadcast = {.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; - if (type != I40E_VSI_MAIN && uplink_vsi == NULL) { + if (type != I40E_VSI_MAIN && type != I40E_VSI_FDIR && + uplink_vsi == NULL) { PMD_DRV_LOG(ERR, "VSI setup failed, " "VSI link shouldn't be NULL\n"); return NULL; @@ -2392,7 +2399,8 @@ i40e_vsi_setup(struct i40e_pf *pf, } /* If uplink vsi didn't setup VEB, create one first */ - if (type != I40E_VSI_MAIN && uplink_vsi->veb == NULL) { + if (type != I40E_VSI_MAIN && type != I40E_VSI_FDIR && + uplink_vsi->veb == NULL) { uplink_vsi->veb = i40e_veb_setup(pf, uplink_vsi); if (NULL == uplink_vsi->veb) { @@ -2420,6 +2428,9 @@ i40e_vsi_setup(struct i40e_pf *pf, case I40E_VSI_SRIOV : vsi->nb_qps = pf->vf_nb_qps; break; + case I40E_VSI_FDIR: + vsi->nb_qps = pf->fdir_nb_qps; + break; default: goto fail_mem; } @@ -2432,7 +2443,7 @@ i40e_vsi_setup(struct i40e_pf *pf, vsi->base_queue = ret; /* VF has MSIX interrupt in VF range, don't allocate here */ - if (type != I40E_VSI_SRIOV) { + if (type != I40E_VSI_SRIOV && type != I40E_VSI_FDIR) { 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); @@ -2561,8 +2572,16 @@ i40e_vsi_setup(struct i40e_pf *pf, * Since VSI is not created yet, only configure parameter, * will add vsi below. */ - } - else { + } else if (type == I40E_VSI_FDIR) { + vsi->info.valid_sections = 0; + vsi->seid = 0; + vsi->vsi_id = 0; + /* + * No actual HW VSI needed, will return here without + * calling adminq and adding to tailq. + */ + return vsi; + } else { PMD_DRV_LOG(ERR, "VSI: Not support other type VSI yet\n"); goto fail_msix_alloc; } @@ -2749,6 +2768,13 @@ i40e_pf_setup(struct i40e_pf *pf) return ret; } + if (pf->flags & I40E_FLAG_FDIR) { + ret = i40e_fdir_setup(pf); + if (ret != I40E_SUCCESS) { + PMD_DRV_LOG(ERR, "Failed to setup flow director\n"); + pf->flags &= ~I40E_FLAG_FDIR; + } + } /* VSI setup */ vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, NULL, 0); if (!vsi) { @@ -2762,6 +2788,8 @@ i40e_pf_setup(struct i40e_pf *pf) /* Configure filter control */ memset(&settings, 0, sizeof(settings)); settings.hash_lut_size = I40E_HASH_LUT_SIZE_128; + if (pf->flags & I40E_FLAG_FDIR) + settings.enable_fdir = TRUE; /* Enable ethtype and macvlan filters */ settings.enable_ethtype = TRUE; settings.enable_macvlan = TRUE; diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h index 64deef2..c2c7fa9 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.h +++ b/lib/librte_pmd_i40e/i40e_ethdev.h @@ -46,11 +46,12 @@ /* number of VSIs and queue default setting */ #define I40E_MAX_QP_NUM_PER_VF 16 #define I40E_DEFAULT_QP_NUM_VMDQ 64 -#define I40E_DEFAULT_QP_NUM_FDIR 64 +#define I40E_DEFAULT_QP_NUM_FDIR 1 #define I40E_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t)) #define I40E_VFTA_SIZE (4096 / I40E_UINT32_BIT_SIZE) /* Default TC traffic in case DCB is not enabled */ #define I40E_DEFAULT_TCMAP 0x1 +#define I40E_FDIR_QUEUE_ID 0 /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -189,6 +190,16 @@ struct i40e_pf_vf { }; /* + * A structure used to define fields of a FDIR related info. + */ +struct i40e_fdir_info { + struct i40e_vsi *fdir_vsi; /* pointer to fdir VSI structure */ + uint16_t match_counter_index; /* Statistic counter index used for fdir*/ + struct i40e_tx_queue *txq; + struct i40e_rx_queue *rxq; +}; + +/* * Structure to store private data specific for PF instance. */ struct i40e_pf { @@ -216,6 +227,7 @@ struct i40e_pf { uint16_t vmdq_nb_qps; /* The number of queue pairs of VMDq */ uint16_t vf_nb_qps; /* The number of queue pairs of VF */ uint16_t fdir_nb_qps; /* The number of queue pairs of Flow Director */ + struct i40e_fdir_info fdir; /* flow director info */ }; enum pending_msg { @@ -312,6 +324,14 @@ void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi); int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, struct i40e_vsi_vlan_pvid_info *info); int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on); +enum i40e_status_code +i40e_fdir_setup_tx_resources(struct i40e_pf *pf, + unsigned int socket_id); +enum i40e_status_code +i40e_fdir_setup_rx_resources(struct i40e_pf *pf, + unsigned int socket_id); +int i40e_fdir_setup(struct i40e_pf *pf); +void i40e_fdir_teardown(struct i40e_pf *pf); /* I40E_DEV_PRIVATE_TO */ #define I40E_DEV_PRIVATE_TO_PF(adapter) \ diff --git a/lib/librte_pmd_i40e/i40e_fdir.c b/lib/librte_pmd_i40e/i40e_fdir.c new file mode 100644 index 0000000..ecb4a95 --- /dev/null +++ b/lib/librte_pmd_i40e/i40e_fdir.c @@ -0,0 +1,135 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "i40e_logs.h" +#include "i40e/i40e_type.h" +#include "i40e_ethdev.h" +#include "i40e_rxtx.h" + +#define I40E_COUNTER_PF 2 +#define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF) + +/* + * i40e_fdir_setup - reserve and initialize the Flow Director resources + * @pf: board private structure + **/ +int +i40e_fdir_setup(struct i40e_pf *pf) +{ + struct i40e_hw *hw = I40E_PF_TO_HW(pf); + struct i40e_vsi *vsi; + int err = I40E_SUCCESS; + + PMD_DRV_LOG(INFO, "FDIR HW Capabilities, guaranteed = %u," + "best_effort = %u.\n", + hw->func_caps.fd_filters_guaranteed, + hw->func_caps.fd_filters_best_effort); + + /* find existing or make new FDIR VSI */ + vsi = pf->fdir.fdir_vsi; + if (!vsi) { + vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, NULL, 0); + if (!vsi) { + PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI\n"); + return I40E_ERR_NO_AVAILABLE_VSI; + } + pf->fdir.fdir_vsi = vsi; + } + /*dev queue setup*/ + err = i40e_fdir_setup_tx_resources(pf, 0); + if (err) { + PMD_DRV_LOG(ERR, "Failed to setup fdir TX resources\n"); + goto fail_setup_tx; + } + err = i40e_fdir_setup_rx_resources(pf, 0); + if (err) { + PMD_DRV_LOG(ERR, "Failed to setup fdir TX resources\n"); + goto fail_setup_rx; + } + + err = i40e_tx_queue_init(pf->fdir.txq); + if (err) { + PMD_DRV_LOG(ERR, "Failed to do fdir TX initialization\n"); + goto fail_mem; + } + + /* need switch on before dev start*/ + err = i40e_switch_tx_queue(hw, vsi->base_queue + I40E_FDIR_QUEUE_ID, TRUE); + if (err) { + PMD_DRV_LOG(ERR, "Failed to do fdir TX initialization\n"); + goto fail_mem; + } + pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id); + return I40E_SUCCESS; + +fail_mem: + i40e_dev_rx_queue_release(pf->fdir.rxq); +fail_setup_rx: + i40e_dev_tx_queue_release(pf->fdir.txq); +fail_setup_tx: + i40e_vsi_release(vsi); + return err; +} + + +/* + * i40e_fdir_teardown - release the Flow Director resources + * @pf: board private structure + */ +void +i40e_fdir_teardown(struct i40e_pf *pf) +{ + struct i40e_vsi *vsi; + + vsi = pf->fdir.fdir_vsi; + i40e_dev_rx_queue_release(pf->fdir.rxq); + pf->fdir.rxq = NULL; + i40e_dev_tx_queue_release(pf->fdir.txq); + pf->fdir.txq = NULL; + i40e_vsi_release(vsi); + pf->fdir.fdir_vsi = NULL; + return; +} diff --git a/lib/librte_pmd_i40e/i40e_rxtx.c b/lib/librte_pmd_i40e/i40e_rxtx.c index 83b9462..ad60d20 100644 --- a/lib/librte_pmd_i40e/i40e_rxtx.c +++ b/lib/librte_pmd_i40e/i40e_rxtx.c @@ -1978,6 +1978,8 @@ i40e_tx_queue_init(struct i40e_tx_queue *txq) tx_ctx.base = txq->tx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; tx_ctx.qlen = txq->nb_tx_desc; tx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[0]); + if (vsi->type == I40E_VSI_FDIR) + tx_ctx.fd_ena = TRUE; err = i40e_clear_lan_tx_queue_context(hw, pf_q); if (err != I40E_SUCCESS) { @@ -2201,3 +2203,128 @@ i40e_dev_clear_queues(struct rte_eth_dev *dev) i40e_reset_rx_queue(dev->data->rx_queues[i]); } } + +enum i40e_status_code +i40e_fdir_setup_tx_resources(struct i40e_pf *pf, + unsigned int socket_id) +{ + struct i40e_tx_queue *txq; + const struct rte_memzone *tz = NULL; + uint32_t ring_size; + struct rte_eth_dev *dev = pf->adapter->eth_dev; + +#define I40E_FDIR_NUM_TX_DESC I40E_MIN_RING_DESC + if (!pf) { + PMD_DRV_LOG(ERR, "PF is not available"); + return I40E_ERR_BAD_PTR; + } + + /* Allocate the TX queue data structure. */ + txq = rte_zmalloc_socket("i40e fdir tx queue", + sizeof(struct i40e_tx_queue), + CACHE_LINE_SIZE, + socket_id); + if (!txq) { + PMD_DRV_LOG(ERR, "Failed to allocate memory for " + "tx queue structure\n"); + return I40E_ERR_NO_MEMORY; + } + + /* Allocate TX hardware ring descriptors. */ + ring_size = sizeof(struct i40e_tx_desc) * I40E_FDIR_NUM_TX_DESC; + ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); + + tz = i40e_ring_dma_zone_reserve(dev, + "fdir_tx_ring", + I40E_FDIR_QUEUE_ID, + ring_size, + socket_id); + if (!tz) { + i40e_dev_tx_queue_release(txq); + PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX\n"); + return I40E_ERR_NO_MEMORY; + } + + txq->nb_tx_desc = I40E_FDIR_NUM_TX_DESC; + txq->queue_id = I40E_FDIR_QUEUE_ID; + txq->reg_idx = pf->fdir.fdir_vsi->base_queue + I40E_FDIR_QUEUE_ID; + txq->vsi = pf->fdir.fdir_vsi; + +#ifdef RTE_LIBRTE_XEN_DOM0 + txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); +#else + txq->tx_ring_phys_addr = (uint64_t)tz->phys_addr; +#endif + txq->tx_ring = (struct i40e_tx_desc *)tz->addr; + /* + * don't need to allocate software ring and reset for the fdir + * program queue just set the queue has been configured. + */ + txq->q_set = TRUE; + pf->fdir.txq = txq; + + return I40E_SUCCESS; +} + +enum i40e_status_code +i40e_fdir_setup_rx_resources(struct i40e_pf *pf, + unsigned int socket_id) +{ + struct i40e_rx_queue *rxq; + const struct rte_memzone *rz = NULL; + uint32_t ring_size; + struct rte_eth_dev *dev = pf->adapter->eth_dev; + +#define I40E_FDIR_NUM_RX_DESC I40E_MIN_RING_DESC + if (!pf) { + PMD_DRV_LOG(ERR, "PF is not available"); + return I40E_ERR_BAD_PTR; + } + + /* Allocate the TX queue data structure. */ + rxq = rte_zmalloc_socket("i40e fdir rx queue", + sizeof(struct i40e_rx_queue), + CACHE_LINE_SIZE, + socket_id); + if (!rxq) { + PMD_DRV_LOG(ERR, "Failed to allocate memory for " + "rx queue structure\n"); + return I40E_ERR_NO_MEMORY; + } + + /* Allocate TX hardware ring descriptors. */ + ring_size = sizeof(union i40e_rx_desc) * I40E_FDIR_NUM_RX_DESC; + ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); + + rz = i40e_ring_dma_zone_reserve(dev, + "fdir_rx_ring", + I40E_FDIR_QUEUE_ID, + ring_size, + socket_id); + if (!rz) { + i40e_dev_rx_queue_release(rxq); + PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX\n"); + return I40E_ERR_NO_MEMORY; + } + + rxq->nb_rx_desc = I40E_FDIR_NUM_RX_DESC; + rxq->queue_id = I40E_FDIR_QUEUE_ID; + rxq->reg_idx = pf->fdir.fdir_vsi->base_queue + I40E_FDIR_QUEUE_ID; + rxq->vsi = pf->fdir.fdir_vsi; + +#ifdef RTE_LIBRTE_XEN_DOM0 + rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); +#else + rxq->rx_ring_phys_addr = (uint64_t)rz->phys_addr; +#endif + rxq->rx_ring = (union i40e_rx_desc *)rz->addr; + + /* + * Don't need to allocate software ring and reset for the fdir + * rx queue, just set the queue has been configured. + */ + rxq->q_set = TRUE; + pf->fdir.rxq = rxq; + + return I40E_SUCCESS; +}