get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1422/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1422,
    "url": "https://patches.dpdk.org/api/patches/1422/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1416530816-2159-2-git-send-email-jingjing.wu@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1416530816-2159-2-git-send-email-jingjing.wu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1416530816-2159-2-git-send-email-jingjing.wu@intel.com",
    "date": "2014-11-21T00:46:35",
    "name": "[dpdk-dev,v6,01/22] i40e: set up and initialize flow director",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "20dde977c237a72d8469674fd13f7151c8a029eb",
    "submitter": {
        "id": 47,
        "url": "https://patches.dpdk.org/api/people/47/?format=api",
        "name": "Jingjing Wu",
        "email": "jingjing.wu@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1416530816-2159-2-git-send-email-jingjing.wu@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1422/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1422/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 62F297FB4;\n\tFri, 21 Nov 2014 01:37:20 +0100 (CET)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby dpdk.org (Postfix) with ESMTP id 0E8257FB4\n\tfor <dev@dpdk.org>; Fri, 21 Nov 2014 01:37:16 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n\tby fmsmga102.fm.intel.com with ESMTP; 20 Nov 2014 16:47:48 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby fmsmga002.fm.intel.com with ESMTP; 20 Nov 2014 16:47:04 -0800",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id sAL0l2PQ003122;\n\tFri, 21 Nov 2014 08:47:02 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid sAL0l0d7002200; Fri, 21 Nov 2014 08:47:02 +0800",
            "(from wujingji@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id sAL0l0DM002196; \n\tFri, 21 Nov 2014 08:47:00 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.07,426,1413270000\"; d=\"scan'208\";a=\"635591939\"",
        "From": "Jingjing Wu <jingjing.wu@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 21 Nov 2014 08:46:35 +0800",
        "Message-Id": "<1416530816-2159-2-git-send-email-jingjing.wu@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1416530816-2159-1-git-send-email-jingjing.wu@intel.com>",
        "References": "<1414654006-7472-1-git-send-email-jingjing.wu@intel.com>\n\t<1416530816-2159-1-git-send-email-jingjing.wu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v6 01/22] i40e: set up and initialize flow\n\tdirector",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "set up fortville resources to support flow director, includes\n - queue 0 pair allocated and set up for flow director\n - create vsi\n - reserve memzone for flow director programming packet\n\nSigned-off-by: jingjing.wu <jingjing.wu@intel.com>\n---\n lib/librte_pmd_i40e/Makefile      |   2 +\n lib/librte_pmd_i40e/i40e_ethdev.c |  78 +++++++--\n lib/librte_pmd_i40e/i40e_ethdev.h |  25 ++-\n lib/librte_pmd_i40e/i40e_fdir.c   | 324 ++++++++++++++++++++++++++++++++++++++\n lib/librte_pmd_i40e/i40e_rxtx.c   | 144 +++++++++++++++++\n 5 files changed, 562 insertions(+), 11 deletions(-)\n create mode 100644 lib/librte_pmd_i40e/i40e_fdir.c",
    "diff": "diff --git a/lib/librte_pmd_i40e/Makefile b/lib/librte_pmd_i40e/Makefile\nindex bd3428f..98e4bdf 100644\n--- a/lib/librte_pmd_i40e/Makefile\n+++ b/lib/librte_pmd_i40e/Makefile\n@@ -91,6 +91,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev.c\n SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_rxtx.c\n SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c\n SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c\n+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c\n+\n # this lib depends upon:\n DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether\n DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf\ndiff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c\nindex 5074262..46115c7 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.c\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.c\n@@ -811,6 +811,18 @@ i40e_dev_start(struct rte_eth_dev *dev)\n \t\ti40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);\n \t}\n \n+\tret = i40e_fdir_configure(dev);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"failed to configure fdir.\");\n+\t\tgoto err_up;\n+\t}\n+\n+\t/* enable FDIR MSIX interrupt */\n+\tif (pf->flags & I40E_FLAG_FDIR) {\n+\t\ti40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi);\n+\t\ti40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi);\n+\t}\n+\n \t/* Enable all queues which have been configured */\n \tret = i40e_dev_switch_queues(pf, TRUE);\n \tif (ret != I40E_SUCCESS) {\n@@ -2818,16 +2830,30 @@ i40e_vsi_setup(struct i40e_pf *pf,\n \tcase I40E_VSI_VMDQ2:\n \t\tvsi->nb_qps = pf->vmdq_nb_qps;\n \t\tbreak;\n+\tcase I40E_VSI_FDIR:\n+\t\tvsi->nb_qps = pf->fdir_nb_qps;\n+\t\tbreak;\n \tdefault:\n \t\tgoto fail_mem;\n \t}\n-\tret = i40e_res_pool_alloc(&pf->qp_pool, vsi->nb_qps);\n-\tif (ret < 0) {\n-\t\tPMD_DRV_LOG(ERR, \"VSI %d allocate queue failed %d\",\n-\t\t\t\tvsi->seid, ret);\n-\t\tgoto fail_mem;\n-\t}\n-\tvsi->base_queue = ret;\n+\t/*\n+\t * The filter status descriptor is reported in rx queue 0,\n+\t * while the tx queue for fdir filter programming has no\n+\t * such constraints, can be non-zero queues.\n+\t * To simplify it, choose FDIR vsi use queue 0 pair.\n+\t * To make sure it will use queue 0 pair, queue allocation\n+\t * need be done before this function is called\n+\t */\n+\tif (type != I40E_VSI_FDIR) {\n+\t\tret = i40e_res_pool_alloc(&pf->qp_pool, vsi->nb_qps);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"VSI %d allocate queue failed %d\",\n+\t\t\t\t\t\tvsi->seid, ret);\n+\t\t\t\tgoto fail_mem;\n+\t\t\t}\n+\t\t\tvsi->base_queue = ret;\n+\t} else\n+\t\tvsi->base_queue = I40E_FDIR_QUEUE_ID;\n \n \t/* VF has MSIX interrupt in VF range, don't allocate here */\n \tif (type != I40E_VSI_SRIOV) {\n@@ -2996,6 +3022,23 @@ i40e_vsi_setup(struct i40e_pf *pf,\n \t\tctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;\n \t\tctxt.info.valid_sections |=\n \t\t\trte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID);\n+\t} else if (type == I40E_VSI_FDIR) {\n+\t\tvsi->uplink_seid = uplink_vsi->uplink_seid;\n+\t\tctxt.pf_num = hw->pf_id;\n+\t\tctxt.vf_num = 0;\n+\t\tctxt.uplink_seid = vsi->uplink_seid;\n+\t\tctxt.connection_type = 0x1;     /* regular data port */\n+\t\tctxt.flags = I40E_AQ_VSI_TYPE_PF;\n+\t\tret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,\n+\t\t\t\t\t\tI40E_DEFAULT_TCMAP);\n+\t\tif (ret != I40E_SUCCESS) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to configure \"\n+\t\t\t\t\t\"TC queue mapping.\");\n+\t\t\tgoto fail_msix_alloc;\n+\t\t}\n+\t\tctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;\n+\t\tctxt.info.valid_sections |=\n+\t\t\trte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID);\n \t} else {\n \t\tPMD_DRV_LOG(ERR, \"VSI: Not support other type VSI yet\");\n \t\tgoto fail_msix_alloc;\n@@ -3184,8 +3227,16 @@ i40e_pf_setup(struct i40e_pf *pf)\n \t\tPMD_DRV_LOG(ERR, \"Could not get switch config, err %d\", ret);\n \t\treturn ret;\n \t}\n-\n-\t/* VSI setup */\n+\tif (pf->flags & I40E_FLAG_FDIR) {\n+\t\t/* make queue allocated first, let FDIR use queue pair 0*/\n+\t\tret = i40e_res_pool_alloc(&pf->qp_pool, I40E_DEFAULT_QP_NUM_FDIR);\n+\t\tif (ret != I40E_FDIR_QUEUE_ID) {\n+\t\t\tPMD_DRV_LOG(ERR, \"queue allocation fails for FDIR :\"\n+\t\t\t\t    \" ret =%d\", ret);\n+\t\t\tpf->flags &= ~I40E_FLAG_FDIR;\n+\t\t}\n+\t}\n+\t/*  main VSI setup */\n \tvsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, NULL, 0);\n \tif (!vsi) {\n \t\tPMD_DRV_LOG(ERR, \"Setup of main vsi failed\");\n@@ -3193,6 +3244,15 @@ i40e_pf_setup(struct i40e_pf *pf)\n \t}\n \tpf->main_vsi = vsi;\n \n+\t/* setup FDIR after main vsi created.*/\n+\tif (pf->flags & I40E_FLAG_FDIR) {\n+\t\tret = i40e_fdir_setup(pf);\n+\t\tif (ret != I40E_SUCCESS) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to setup flow director.\");\n+\t\t\tpf->flags &= ~I40E_FLAG_FDIR;\n+\t\t}\n+\t}\n+\n \t/* Configure filter control */\n \tmemset(&settings, 0, sizeof(settings));\n \tsettings.hash_lut_size = I40E_HASH_LUT_SIZE_128;\ndiff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h\nindex 96361c2..e9c714c 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.h\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.h\n@@ -47,11 +47,12 @@\n #define I40E_QUEUE_BASE_ADDR_UNIT 128\n /* number of VSIs and queue default setting */\n #define I40E_MAX_QP_NUM_PER_VF    16\n-#define I40E_DEFAULT_QP_NUM_FDIR  64\n+#define I40E_DEFAULT_QP_NUM_FDIR  1\n #define I40E_UINT32_BIT_SIZE      (CHAR_BIT * sizeof(uint32_t))\n #define I40E_VFTA_SIZE            (4096 / I40E_UINT32_BIT_SIZE)\n /* Default TC traffic in case DCB is not enabled */\n #define I40E_DEFAULT_TCMAP        0x1\n+#define I40E_FDIR_QUEUE_ID        0\n \n /* Always assign pool 0 to main VSI, VMDQ will start from 1 */\n #define I40E_VMDQ_POOL_BASE       1\n@@ -243,6 +244,18 @@ struct i40e_vmdq_info {\n };\n \n /*\n+ *  A structure used to define fields of a FDIR related info.\n+ */\n+struct i40e_fdir_info {\n+\tstruct i40e_vsi *fdir_vsi;     /* pointer to fdir VSI structure */\n+\tuint16_t match_counter_index;  /* Statistic counter index used for fdir*/\n+\tstruct i40e_tx_queue *txq;\n+\tstruct i40e_rx_queue *rxq;\n+\tvoid *prg_pkt;                 /* memory for fdir program packet */\n+\tuint64_t dma_addr;             /* physic address of packet memory*/\n+};\n+\n+/*\n  * Structure to store private data specific for PF instance.\n  */\n struct i40e_pf {\n@@ -270,7 +283,6 @@ struct i40e_pf {\n \tuint16_t vmdq_nb_qps; /* The number of queue pairs of VMDq */\n \tuint16_t vf_nb_qps; /* The number of queue pairs of VF */\n \tuint16_t fdir_nb_qps; /* The number of queue pairs of Flow Director */\n-\n \t/* store VXLAN UDP ports */\n \tuint16_t vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];\n \tuint16_t vxlan_bitmap; /* Vxlan bit mask */\n@@ -279,6 +291,8 @@ struct i40e_pf {\n \tuint16_t max_nb_vmdq_vsi; /* Max number of VMDQ VSIs supported */\n \tuint16_t nb_cfg_vmdq_vsi; /* number of VMDQ VSIs configured */\n \tstruct i40e_vmdq_info *vmdq;\n+\n+\tstruct i40e_fdir_info fdir; /* flow director info */\n };\n \n enum pending_msg {\n@@ -380,6 +394,13 @@ int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,\n int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);\n uint64_t i40e_config_hena(uint64_t flags);\n uint64_t i40e_parse_hena(uint64_t flags);\n+enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);\n+enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);\n+int i40e_fdir_setup(struct i40e_pf *pf);\n+const struct rte_memzone *i40e_memzone_reserve(const char *name,\n+\t\t\t\t\tuint32_t len,\n+\t\t\t\t\tint socket_id);\n+int i40e_fdir_configure(struct rte_eth_dev *dev);\n \n /* I40E_DEV_PRIVATE_TO */\n #define I40E_DEV_PRIVATE_TO_PF(adapter) \\\ndiff --git a/lib/librte_pmd_i40e/i40e_fdir.c b/lib/librte_pmd_i40e/i40e_fdir.c\nnew file mode 100644\nindex 0000000..7708887\n--- /dev/null\n+++ b/lib/librte_pmd_i40e/i40e_fdir.c\n@@ -0,0 +1,324 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <sys/queue.h>\n+#include <stdio.h>\n+#include <errno.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <stdarg.h>\n+\n+#include <rte_ether.h>\n+#include <rte_ethdev.h>\n+#include <rte_log.h>\n+#include <rte_memzone.h>\n+#include <rte_malloc.h>\n+\n+#include \"i40e_logs.h\"\n+#include \"i40e/i40e_type.h\"\n+#include \"i40e_ethdev.h\"\n+#include \"i40e_rxtx.h\"\n+\n+#define I40E_FDIR_MZ_NAME          \"FDIR_MEMZONE\"\n+#define I40E_FDIR_PKT_LEN                   512\n+\n+\n+/* Wait count and interval for fdir filter flush */\n+#define I40E_FDIR_FLUSH_RETRY       50\n+#define I40E_FDIR_FLUSH_INTERVAL_MS 5\n+\n+#define I40E_COUNTER_PF           2\n+/* Statistic counter index for one pf */\n+#define I40E_COUNTER_INDEX_FDIR(pf_id)   (0 + (pf_id) * I40E_COUNTER_PF)\n+#define I40E_FLX_OFFSET_IN_FIELD_VECTOR   50\n+\n+static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq);\n+static int i40e_fdir_flush(struct rte_eth_dev *dev);\n+\n+static int\n+i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)\n+{\n+\tstruct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi);\n+\tstruct i40e_hmc_obj_rxq rx_ctx;\n+\tint err = I40E_SUCCESS;\n+\n+\tmemset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));\n+\t/* Init the RX queue in hardware */\n+\trx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT;\n+\trx_ctx.hbuff = 0;\n+\trx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT;\n+\trx_ctx.qlen = rxq->nb_rx_desc;\n+#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC\n+\trx_ctx.dsize = 1;\n+#endif\n+\trx_ctx.dtype = i40e_header_split_none;\n+\trx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;\n+\trx_ctx.rxmax = ETHER_MAX_LEN;\n+\trx_ctx.tphrdesc_ena = 1;\n+\trx_ctx.tphwdesc_ena = 1;\n+\trx_ctx.tphdata_ena = 1;\n+\trx_ctx.tphhead_ena = 1;\n+\trx_ctx.lrxqthresh = 2;\n+\trx_ctx.crcstrip = 0;\n+\trx_ctx.l2tsel = 1;\n+\trx_ctx.showiv = 1;\n+\trx_ctx.prefena = 1;\n+\n+\terr = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx);\n+\tif (err != I40E_SUCCESS) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to clear FDIR RX queue context.\");\n+\t\treturn err;\n+\t}\n+\terr = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx);\n+\tif (err != I40E_SUCCESS) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to set FDIR RX queue context.\");\n+\t\treturn err;\n+\t}\n+\trxq->qrx_tail = hw->hw_addr +\n+\t\tI40E_QRX_TAIL(rxq->vsi->base_queue);\n+\n+\trte_wmb();\n+\t/* Init the RX tail regieter. */\n+\tI40E_PCI_REG_WRITE(rxq->qrx_tail, 0);\n+\tI40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);\n+\n+\treturn err;\n+}\n+\n+/*\n+ * i40e_fdir_setup - reserve and initialize the Flow Director resources\n+ * @pf: board private structure\n+ */\n+int\n+i40e_fdir_setup(struct i40e_pf *pf)\n+{\n+\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n+\tstruct i40e_vsi *vsi;\n+\tint err = I40E_SUCCESS;\n+\tchar z_name[RTE_MEMZONE_NAMESIZE];\n+\tconst struct rte_memzone *mz = NULL;\n+\tstruct rte_eth_dev *eth_dev = pf->adapter->eth_dev;\n+\n+\tPMD_DRV_LOG(INFO, \"FDIR HW Capabilities: num_filters_guaranteed = %u,\"\n+\t\t\t\" num_filters_best_effort = %u.\",\n+\t\t\thw->func_caps.fd_filters_guaranteed,\n+\t\t\thw->func_caps.fd_filters_best_effort);\n+\n+\tvsi = pf->fdir.fdir_vsi;\n+\tif (vsi) {\n+\t\tPMD_DRV_LOG(ERR, \"FDIR vsi pointer needs\"\n+\t\t\t\t \"to be null before creation.\");\n+\t\treturn I40E_ERR_BAD_PTR;\n+\t}\n+\t/* make new FDIR VSI */\n+\tvsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);\n+\tif (!vsi) {\n+\t\tPMD_DRV_LOG(ERR, \"Couldn't create FDIR VSI.\");\n+\t\treturn I40E_ERR_NO_AVAILABLE_VSI;\n+\t}\n+\tpf->fdir.fdir_vsi = vsi;\n+\n+\t/*Fdir tx queue setup*/\n+\terr = i40e_fdir_setup_tx_resources(pf);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to setup FDIR TX resources.\");\n+\t\tgoto fail_setup_tx;\n+\t}\n+\n+\t/*Fdir rx queue setup*/\n+\terr = i40e_fdir_setup_rx_resources(pf);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to setup FDIR RX resources.\");\n+\t\tgoto fail_setup_rx;\n+\t}\n+\n+\terr = i40e_tx_queue_init(pf->fdir.txq);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to do FDIR TX initialization.\");\n+\t\tgoto fail_mem;\n+\t}\n+\n+\t/* need switch on before dev start*/\n+\terr = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to do fdir TX switch on.\");\n+\t\tgoto fail_mem;\n+\t}\n+\n+\t/* Init the rx queue in hardware */\n+\terr = i40e_fdir_rx_queue_init(pf->fdir.rxq);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to do FDIR RX initialization.\");\n+\t\tgoto fail_mem;\n+\t}\n+\n+\t/* switch on rx queue */\n+\terr = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to do FDIR RX switch on.\");\n+\t\tgoto fail_mem;\n+\t}\n+\n+\t/* reserve memory for the fdir programming packet */\n+\tsnprintf(z_name, sizeof(z_name), \"%s_%s_%d\",\n+\t\t\teth_dev->driver->pci_drv.name,\n+\t\t\tI40E_FDIR_MZ_NAME,\n+\t\t\teth_dev->data->port_id);\n+\tmz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);\n+\tif (!mz) {\n+\t\tPMD_DRV_LOG(ERR, \"Cannot init memzone for\"\n+\t\t\t\t \"flow director program packet.\");\n+\t\terr = I40E_ERR_NO_MEMORY;\n+\t\tgoto fail_mem;\n+\t}\n+\tpf->fdir.prg_pkt = mz->addr;\n+#ifdef RTE_LIBRTE_XEN_DOM0\n+\tpf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);\n+#else\n+\tpf->fdir.dma_addr = (uint64_t)mz->phys_addr;\n+#endif\n+\tpf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);\n+\tPMD_DRV_LOG(INFO, \"FDIR setup successfully, with programming queue %u.\",\n+\t\t    vsi->base_queue);\n+\treturn I40E_SUCCESS;\n+\n+fail_mem:\n+\ti40e_dev_rx_queue_release(pf->fdir.rxq);\n+\tpf->fdir.rxq = NULL;\n+fail_setup_rx:\n+\ti40e_dev_tx_queue_release(pf->fdir.txq);\n+\tpf->fdir.txq = NULL;\n+fail_setup_tx:\n+\ti40e_vsi_release(vsi);\n+\tpf->fdir.fdir_vsi = NULL;\n+\treturn err;\n+}\n+\n+/* check whether the flow director table in empty */\n+static inline int\n+i40e_fdir_empty(struct i40e_hw *hw)\n+{\n+\tuint32_t guarant_cnt, best_cnt;\n+\n+\tguarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &\n+\t\t\t\t I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>\n+\t\t\t\t I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);\n+\tbest_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &\n+\t\t\t      I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>\n+\t\t\t      I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);\n+\tif (best_cnt + guarant_cnt > 0)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Configure flow director related setting\n+ */\n+int\n+i40e_fdir_configure(struct rte_eth_dev *dev)\n+{\n+\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tuint32_t val;\n+\tint ret = 0;\n+\n+\t/*\n+\t* configuration need to be done before\n+\t* flow director filters are added\n+\t* If filters exist, flush them.\n+\t*/\n+\tif (i40e_fdir_empty(hw) < 0) {\n+\t\tret = i40e_fdir_flush(dev);\n+\t\tif (ret) {\n+\t\t\tPMD_DRV_LOG(ERR, \"failed to flush fdir table.\");\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tval = I40E_READ_REG(hw, I40E_PFQF_CTL_0);\n+\tif ((pf->flags & I40E_FLAG_FDIR) &&\n+\t\tdev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) {\n+\t\t/* enable FDIR filter */\n+\t\tval |= I40E_PFQF_CTL_0_FD_ENA_MASK;\n+\t\tI40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);\n+\t} else {\n+\t\t/* disable FDIR filter */\n+\t\tval &= ~I40E_PFQF_CTL_0_FD_ENA_MASK;\n+\t\tI40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);\n+\t\tpf->flags &= ~I40E_FLAG_FDIR;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/*\n+ * i40e_fdir_flush - clear all filters of Flow Director table\n+ * @pf: board private structure\n+ */\n+static int\n+i40e_fdir_flush(struct rte_eth_dev *dev)\n+{\n+\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n+\tuint32_t reg;\n+\tuint16_t guarant_cnt, best_cnt;\n+\tint i;\n+\n+\tI40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);\n+\tI40E_WRITE_FLUSH(hw);\n+\n+\tfor (i = 0; i < I40E_FDIR_FLUSH_RETRY; i++) {\n+\t\trte_delay_ms(I40E_FDIR_FLUSH_INTERVAL_MS);\n+\t\treg = I40E_READ_REG(hw, I40E_PFQF_CTL_1);\n+\t\tif (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))\n+\t\t\tbreak;\n+\t}\n+\tif (i >= I40E_FDIR_FLUSH_RETRY) {\n+\t\tPMD_DRV_LOG(ERR, \"FD table did not flush, may need more time.\");\n+\t\treturn -ETIMEDOUT;\n+\t}\n+\tguarant_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &\n+\t\t\t\tI40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>\n+\t\t\t\tI40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);\n+\tbest_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &\n+\t\t\t\tI40E_PFQF_FDSTAT_BEST_CNT_MASK) >>\n+\t\t\t\tI40E_PFQF_FDSTAT_BEST_CNT_SHIFT);\n+\tif (guarant_cnt != 0 || best_cnt != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to flush FD table.\");\n+\t\treturn -ENOSYS;\n+\t} else\n+\t\tPMD_DRV_LOG(INFO, \"FD table Flush success.\");\n+\treturn 0;\n+}\ndiff --git a/lib/librte_pmd_i40e/i40e_rxtx.c b/lib/librte_pmd_i40e/i40e_rxtx.c\nindex 487591d..1c5cfd6 100644\n--- a/lib/librte_pmd_i40e/i40e_rxtx.c\n+++ b/lib/librte_pmd_i40e/i40e_rxtx.c\n@@ -2098,6 +2098,24 @@ i40e_ring_dma_zone_reserve(struct rte_eth_dev *dev,\n #endif\n }\n \n+const struct rte_memzone *\n+i40e_memzone_reserve(const char *name, uint32_t len, int socket_id)\n+{\n+\tconst struct rte_memzone *mz = NULL;\n+\n+\tmz = rte_memzone_lookup(name);\n+\tif (mz)\n+\t\treturn mz;\n+#ifdef RTE_LIBRTE_XEN_DOM0\n+\tmz = rte_memzone_reserve_bounded(name, len,\n+\t\tsocket_id, 0, I40E_ALIGN, RTE_PGSIZE_2M);\n+#else\n+\tmz = rte_memzone_reserve_aligned(name, len,\n+\t\t\t\tsocket_id, 0, I40E_ALIGN);\n+#endif\n+\treturn mz;\n+}\n+\n void\n i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq)\n {\n@@ -2231,6 +2249,8 @@ i40e_tx_queue_init(struct i40e_tx_queue *txq)\n \ttx_ctx.base = txq->tx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT;\n \ttx_ctx.qlen = txq->nb_tx_desc;\n \ttx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[0]);\n+\tif (vsi->type == I40E_VSI_FDIR)\n+\t\ttx_ctx.fd_ena = TRUE;\n \n \terr = i40e_clear_lan_tx_queue_context(hw, pf_q);\n \tif (err != I40E_SUCCESS) {\n@@ -2447,3 +2467,127 @@ i40e_dev_clear_queues(struct rte_eth_dev *dev)\n \t\ti40e_reset_rx_queue(dev->data->rx_queues[i]);\n \t}\n }\n+\n+#define I40E_FDIR_NUM_TX_DESC  I40E_MIN_RING_DESC\n+#define I40E_FDIR_NUM_RX_DESC  I40E_MIN_RING_DESC\n+\n+enum i40e_status_code\n+i40e_fdir_setup_tx_resources(struct i40e_pf *pf)\n+{\n+\tstruct i40e_tx_queue *txq;\n+\tconst struct rte_memzone *tz = NULL;\n+\tuint32_t ring_size;\n+\tstruct rte_eth_dev *dev = pf->adapter->eth_dev;\n+\n+\tif (!pf) {\n+\t\tPMD_DRV_LOG(ERR, \"PF is not available\");\n+\t\treturn I40E_ERR_BAD_PTR;\n+\t}\n+\n+\t/* Allocate the TX queue data structure. */\n+\ttxq = rte_zmalloc_socket(\"i40e fdir tx queue\",\n+\t\t\t\t  sizeof(struct i40e_tx_queue),\n+\t\t\t\t  CACHE_LINE_SIZE,\n+\t\t\t\t  SOCKET_ID_ANY);\n+\tif (!txq) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to allocate memory for \"\n+\t\t\t\t\t\"tx queue structure.\");\n+\t\treturn I40E_ERR_NO_MEMORY;\n+\t}\n+\n+\t/* Allocate TX hardware ring descriptors. */\n+\tring_size = sizeof(struct i40e_tx_desc) * I40E_FDIR_NUM_TX_DESC;\n+\tring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN);\n+\n+\ttz = i40e_ring_dma_zone_reserve(dev,\n+\t\t\t\t\t\"fdir_tx_ring\",\n+\t\t\t\t\tI40E_FDIR_QUEUE_ID,\n+\t\t\t\t\tring_size,\n+\t\t\t\t\tSOCKET_ID_ANY);\n+\tif (!tz) {\n+\t\ti40e_dev_tx_queue_release(txq);\n+\t\tPMD_DRV_LOG(ERR, \"Failed to reserve DMA memory for TX.\");\n+\t\treturn I40E_ERR_NO_MEMORY;\n+\t}\n+\n+\ttxq->nb_tx_desc = I40E_FDIR_NUM_TX_DESC;\n+\ttxq->queue_id = I40E_FDIR_QUEUE_ID;\n+\ttxq->reg_idx = pf->fdir.fdir_vsi->base_queue;\n+\ttxq->vsi = pf->fdir.fdir_vsi;\n+\n+#ifdef RTE_LIBRTE_XEN_DOM0\n+\ttxq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);\n+#else\n+\ttxq->tx_ring_phys_addr = (uint64_t)tz->phys_addr;\n+#endif\n+\ttxq->tx_ring = (struct i40e_tx_desc *)tz->addr;\n+\t/*\n+\t * don't need to allocate software ring and reset for the fdir\n+\t * program queue just set the queue has been configured.\n+\t */\n+\ttxq->q_set = TRUE;\n+\tpf->fdir.txq = txq;\n+\n+\treturn I40E_SUCCESS;\n+}\n+\n+enum i40e_status_code\n+i40e_fdir_setup_rx_resources(struct i40e_pf *pf)\n+{\n+\tstruct i40e_rx_queue *rxq;\n+\tconst struct rte_memzone *rz = NULL;\n+\tuint32_t ring_size;\n+\tstruct rte_eth_dev *dev = pf->adapter->eth_dev;\n+\n+\tif (!pf) {\n+\t\tPMD_DRV_LOG(ERR, \"PF is not available\");\n+\t\treturn I40E_ERR_BAD_PTR;\n+\t}\n+\n+\t/* Allocate the RX queue data structure. */\n+\trxq = rte_zmalloc_socket(\"i40e fdir rx queue\",\n+\t\t\t\t  sizeof(struct i40e_rx_queue),\n+\t\t\t\t  CACHE_LINE_SIZE,\n+\t\t\t\t  SOCKET_ID_ANY);\n+\tif (!rxq) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to allocate memory for \"\n+\t\t\t\t\t\"rx queue structure.\");\n+\t\treturn I40E_ERR_NO_MEMORY;\n+\t}\n+\n+\t/* Allocate RX hardware ring descriptors. */\n+\tring_size = sizeof(union i40e_rx_desc) * I40E_FDIR_NUM_RX_DESC;\n+\tring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN);\n+\n+\trz = i40e_ring_dma_zone_reserve(dev,\n+\t\t\t\t\t\"fdir_rx_ring\",\n+\t\t\t\t\tI40E_FDIR_QUEUE_ID,\n+\t\t\t\t\tring_size,\n+\t\t\t\t\tSOCKET_ID_ANY);\n+\tif (!rz) {\n+\t\ti40e_dev_rx_queue_release(rxq);\n+\t\tPMD_DRV_LOG(ERR, \"Failed to reserve DMA memory for RX.\");\n+\t\treturn I40E_ERR_NO_MEMORY;\n+\t}\n+\n+\trxq->nb_rx_desc = I40E_FDIR_NUM_RX_DESC;\n+\trxq->queue_id = I40E_FDIR_QUEUE_ID;\n+\trxq->reg_idx = pf->fdir.fdir_vsi->base_queue;\n+\trxq->vsi = pf->fdir.fdir_vsi;\n+\n+#ifdef RTE_LIBRTE_XEN_DOM0\n+\trxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);\n+#else\n+\trxq->rx_ring_phys_addr = (uint64_t)rz->phys_addr;\n+#endif\n+\trxq->rx_ring = (union i40e_rx_desc *)rz->addr;\n+\n+\t/*\n+\t * Don't need to allocate software ring and reset for the fdir\n+\t * rx queue, just set the queue has been configured.\n+\t */\n+\trxq->q_set = TRUE;\n+\tpf->fdir.rxq = rxq;\n+\n+\treturn I40E_SUCCESS;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "01/22"
    ]
}