get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1351,
    "url": "https://patches.dpdk.org/api/patches/1351/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1416409096-1340-3-git-send-email-helin.zhang@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": "<1416409096-1340-3-git-send-email-helin.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1416409096-1340-3-git-send-email-helin.zhang@intel.com",
    "date": "2014-11-19T14:58:15",
    "name": "[dpdk-dev,v6,2/3] i40e: support of controlling hash functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "318df904c53ec01a4f9ccd0eabcfb34b5f937779",
    "submitter": {
        "id": 14,
        "url": "https://patches.dpdk.org/api/people/14/?format=api",
        "name": "Zhang, Helin",
        "email": "helin.zhang@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1416409096-1340-3-git-send-email-helin.zhang@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1351/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1351/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 5D43C7F78;\n\tWed, 19 Nov 2014 15:48:10 +0100 (CET)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby dpdk.org (Postfix) with ESMTP id 3E03E7F95\n\tfor <dev@dpdk.org>; Wed, 19 Nov 2014 15:48:05 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n\tby fmsmga101.fm.intel.com with ESMTP; 19 Nov 2014 06:58:30 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby fmsmga002.fm.intel.com with ESMTP; 19 Nov 2014 06:58:28 -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 sAJEwQF4032271;\n\tWed, 19 Nov 2014 22:58:26 +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 sAJEwNkw001389; Wed, 19 Nov 2014 22:58:25 +0800",
            "(from hzhan75@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id sAJEwNEF001385; \n\tWed, 19 Nov 2014 22:58:23 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.07,417,1413270000\"; d=\"scan'208\";a=\"634549603\"",
        "From": "Helin Zhang <helin.zhang@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed, 19 Nov 2014 22:58:15 +0800",
        "Message-Id": "<1416409096-1340-3-git-send-email-helin.zhang@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1416409096-1340-1-git-send-email-helin.zhang@intel.com>",
        "References": "<1413861289-26662-1-git-send-email-helin.zhang@intel.com>\n\t<1416409096-1340-1-git-send-email-helin.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v6 2/3] i40e: support of controlling hash\n\tfunctions",
        "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": "Hash filter control has been implemented for i40e. It includes\ngetting/setting,\n- hash function type\n- symmetric hash enable per pctype (packet classification type)\n- symmetric hash enable per port\n- filter swap configuration\n\nSigned-off-by: Helin Zhang <helin.zhang@intel.com>\n---\n lib/librte_ether/rte_eth_ctrl.h   |  98 +++++++++-\n lib/librte_pmd_i40e/i40e_ethdev.c | 389 ++++++++++++++++++++++++++++++++++++++\n 2 files changed, 482 insertions(+), 5 deletions(-)\n\nv5 changes:\n* Integrated with filter API defined recently.\n\nv6 changes:\n* Implemented the mapping function to convert RSS offload types to\n  Packet Classification Types, to isolate the real hardware\n  specific things.\n* Removed initialization of global registers in i40e PMD, as global\n  registers shouldn't be initialized per port.\n* Added more annotations to get code more understandable.\n* Corrected annotation format for documenation.",
    "diff": "diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h\nindex 8dd384d..1dab7d0 100644\n--- a/lib/librte_ether/rte_eth_ctrl.h\n+++ b/lib/librte_ether/rte_eth_ctrl.h\n@@ -51,6 +51,7 @@ extern \"C\" {\n  */\n enum rte_filter_type {\n \tRTE_ETH_FILTER_NONE = 0,\n+\tRTE_ETH_FILTER_HASH,\n \tRTE_ETH_FILTER_MACVLAN,\n \tRTE_ETH_FILTER_TUNNEL,\n \tRTE_ETH_FILTER_MAX\n@@ -60,29 +61,116 @@ enum rte_filter_type {\n  * Generic operations on filters\n  */\n enum rte_filter_op {\n+\t/** used to check whether the type filter is supported */\n \tRTE_ETH_FILTER_NOP = 0,\n-\t/**< used to check whether the type filter is supported */\n \tRTE_ETH_FILTER_ADD,      /**< add filter entry */\n \tRTE_ETH_FILTER_UPDATE,   /**< update filter entry */\n \tRTE_ETH_FILTER_DELETE,   /**< delete filter entry */\n \tRTE_ETH_FILTER_FLUSH,    /**< flush all entries */\n \tRTE_ETH_FILTER_GET,      /**< get filter entry */\n \tRTE_ETH_FILTER_SET,      /**< configurations */\n+\t/** get information of filter, such as status or statistics */\n \tRTE_ETH_FILTER_INFO,\n-\t/**< get information of filter, such as status or statistics */\n \tRTE_ETH_FILTER_OP_MAX\n };\n \n /**\n+ * Hash filter information types.\n+ * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE is for getting/setting the\n+ *   information/configuration of 'symmetric hash enable' per flow type.\n+ * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT is for getting/setting the\n+ *   information/configuration of 'symmetric hash enable' per port.\n+ * - RTE_ETH_HASH_FILTER_SWAP is for getting/setting the swap\n+ *   information/configuration which is for symmetric hash function.\n+ * - RTE_ETH_HASH_FILTER_HASH_FUNCTION is for getting/setting the hash function\n+ *   which could be Toeplitz or Simple Xor.\n+ */\n+enum rte_eth_hash_filter_info_type {\n+\tRTE_ETH_HASH_FILTER_INFO_TYPE_UNKNOWN = 0,\n+\t/** Symmetric hash enable per flow type */\n+\tRTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE,\n+\t/** Symmetric hash enable per port */\n+\tRTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT,\n+\t/** Hash filter swap */\n+\tRTE_ETH_HASH_FILTER_SWAP,\n+\t/** Hash function */\n+\tRTE_ETH_HASH_FILTER_HASH_FUNCTION,\n+\tRTE_ETH_HASH_FILTER_INFO_TYPE_MAX,\n+};\n+\n+/**\n+ * Hash function types.\n+ */\n+enum rte_eth_hash_function {\n+\tRTE_ETH_HASH_FUNCTION_UNKNOWN = 0,\n+\tRTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */\n+\tRTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */\n+\tRTE_ETH_HASH_FUNCTION_MAX,\n+};\n+\n+/**\n+ * A structure used to set or get symmetric hash enable information, to support\n+ * 'RTE_ETH_FILTER_HASH', 'RTE_ETH_FILTER_GET/RTE_ETH_FILTER_SET', with\n+ * information type 'RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE'.\n+ * The flow type could be 'ETH_RSS_<*>_SHIFT' which is defined in rte_ethdev.h.\n+ */\n+struct rte_eth_sym_hash_ena_info {\n+\t/** Flow type, defined in rte_ethdev.h */\n+\tuint8_t flow_type;\n+\tuint8_t enable; /**< Enable or disable flag */\n+};\n+\n+/**\n+ * A structure used to set or get filter swap information, to support\n+ * 'RTE_ETH_FILTER_HASH', 'RTE_ETH_FILTER_GET/RTE_ETH_FILTER_SET',\n+ * with information type 'RTE_ETH_HASH_FILTER_SWAP'.\n+ * The flow type could be 'ETH_RSS_<*>_SHIFT' which is defined in rte_ethdev.h.\n+ */\n+struct rte_eth_filter_swap_info {\n+\t/** Flow type, defined in rte_ethdev.h */\n+\tuint8_t flow_type;\n+\t/** Offset of the 1st field of the 1st couple to be swapped. */\n+\tuint8_t off0_src0;\n+\t/** Offset of the 2nd field of the 1st couple to be swapped. */\n+\tuint8_t off0_src1;\n+\t/** Field length of the first couple. */\n+\tuint8_t len0;\n+\t/** Offset of the 1st field of the 2nd couple to be swapped. */\n+\tuint8_t off1_src0;\n+\t/** Offset of the 2nd field of the 2nd couple to be swapped. */\n+\tuint8_t off1_src1;\n+\t/** Field length of the second couple. */\n+\tuint8_t len1;\n+};\n+\n+/**\n+ * A structure used to set or get hash filter information, to support filter\n+ * type of 'RTE_ETH_FILTER_HASH' and its operations.\n+ */\n+struct rte_eth_hash_filter_info {\n+\tenum rte_eth_hash_filter_info_type info_type; /**< Information type. */\n+\t/** Details of hash filter infomation */\n+\tunion {\n+\t\t/* For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE */\n+\t\tstruct rte_eth_sym_hash_ena_info sym_hash_ena;\n+\t\t/* For RTE_ETH_HASH_FILTER_SWAP */\n+\t\tstruct rte_eth_filter_swap_info filter_swap;\n+\t\t/* For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT */\n+\t\tuint8_t enable;\n+\t\t/* For RTE_ETH_HASH_FILTER_HASH_FUNCTION */\n+\t\tenum rte_eth_hash_function hash_function;\n+\t} info;\n+};\n+\n+/*\n  * MAC filter type\n  */\n enum rte_mac_filter_type {\n \tRTE_MAC_PERFECT_MATCH = 1, /**< exact match of MAC addr. */\n-\tRTE_MACVLAN_PERFECT_MATCH,\n-\t/**< exact match of MAC addr and VLAN ID. */\n+\tRTE_MACVLAN_PERFECT_MATCH, /**< exact match of MAC addr and VLAN ID. */\n \tRTE_MAC_HASH_MATCH, /**< hash match of MAC addr. */\n+\t/** hash match of MAC addr and exact match of VLAN ID. */\n \tRTE_MACVLAN_HASH_MATCH,\n-\t/**< hash match of MAC addr and exact match of VLAN ID. */\n };\n \n /**\ndiff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c\nindex 9096802..4ec609b 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.c\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.c\n@@ -99,6 +99,10 @@\n \n #define I40E_PRE_TX_Q_CFG_WAIT_US       10 /* 10 us */\n \n+/* Field max of swap configurations for symmetric hash */\n+#define I40E_SWAP_FIELD_LEN_MAX         0x1F\n+#define I40E_SWAP_FIELD_OFFSET_MAX      0x7F\n+\n /* Mask of PF interrupt causes */\n #define I40E_PFINT_ICR0_ENA_MASK ( \\\n \t\tI40E_PFINT_ICR0_ENA_ECC_ERR_MASK | \\\n@@ -209,6 +213,8 @@ static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n \t\t\t\tenum rte_filter_type filter_type,\n \t\t\t\tenum rte_filter_op filter_op,\n \t\t\t\tvoid *arg);\n+static void i40e_hw_init(struct i40e_hw *hw);\n+static uint8_t i40e_flow_type_to_pctype(uint64_t type);\n \n static struct rte_pci_id pci_id_i40e_map[] = {\n #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},\n@@ -379,6 +385,9 @@ eth_i40e_dev_init(__rte_unused struct eth_driver *eth_drv,\n \t/* Make sure all is clean before doing PF reset */\n \ti40e_clear_hw(hw);\n \n+\t/* Initialize the hardware */\n+\ti40e_hw_init(hw);\n+\n \t/* Reset here to make sure all is clean for each PF */\n \tret = i40e_pf_reset(hw);\n \tif (ret) {\n@@ -4990,6 +4999,328 @@ i40e_pf_config_mq_rx(struct i40e_pf *pf)\n \treturn ret;\n }\n \n+/* Get the symmetric hash enable configurations per flow type */\n+static int\n+i40e_get_symmetric_hash_enable_per_flow_type(struct i40e_hw *hw,\n+\t\t\tstruct rte_eth_sym_hash_ena_info *info)\n+{\n+\tuint32_t reg;\n+\tuint8_t pctype = i40e_flow_type_to_pctype(info->flow_type);\n+\n+\tif (pctype > 0) {\n+\t\treg = I40E_READ_REG(hw, I40E_GLQF_HSYM(pctype));\n+\t\tinfo->enable = reg & I40E_GLQF_HSYM_SYMH_ENA_MASK ? 1 : 0;\n+\t\treturn 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"RSS type[%u] not supported\", info->flow_type);\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+/* Set the symmetric hash enable configurations per flow type */\n+static int\n+i40e_set_symmetric_hash_enable_per_flow_type(struct i40e_hw *hw,\n+\t\tconst struct rte_eth_sym_hash_ena_info *info)\n+{\n+\tuint32_t reg;\n+\tuint8_t pctype = i40e_flow_type_to_pctype(info->flow_type);\n+\n+\tif (pctype > 0) {\n+\t\treg = info->enable ? I40E_GLQF_HSYM_SYMH_ENA_MASK : 0;\n+\t\tI40E_WRITE_REG(hw, I40E_GLQF_HSYM(pctype), reg);\n+\t\tI40E_WRITE_FLUSH(hw);\n+\t\treturn 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"RSS type[%u] not supported\", info->flow_type);\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+/* Get the symmetric hash enable configurations per port */\n+static void\n+i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable)\n+{\n+\tuint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0);\n+\n+\t*enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0;\n+}\n+\n+/* Set the symmetric hash enable configurations per port */\n+static void\n+i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable)\n+{\n+\tuint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0);\n+\n+\tif (enable > 0) {\n+\t\tif (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) {\n+\t\t\tPMD_DRV_LOG(INFO, \"Symmetric hash has already \"\n+\t\t\t\t\t\t\t\"been enabled\");\n+\t\t\treturn;\n+\t\t}\n+\t\treg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK;\n+\t} else {\n+\t\tif (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) {\n+\t\t\tPMD_DRV_LOG(INFO, \"Symmetric hash has already \"\n+\t\t\t\t\t\t\t\"been disabled\");\n+\t\t\treturn;\n+\t\t}\n+\t\treg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK;\n+\t}\n+\tI40E_WRITE_REG(hw, I40E_PRTQF_CTL_0, reg);\n+\tI40E_WRITE_FLUSH(hw);\n+}\n+\n+/* Get filter swap configurations */\n+static int\n+i40e_get_filter_swap(struct i40e_hw *hw, struct rte_eth_filter_swap_info *info)\n+{\n+\tuint32_t reg;\n+\tuint8_t pctype = i40e_flow_type_to_pctype(info->flow_type);\n+\n+\tif (pctype > 0) {\n+\t\treg = I40E_READ_REG(hw, I40E_GLQF_SWAP(0, pctype));\n+\t\tPMD_DRV_LOG(DEBUG, \"Value read from I40E_GLQF_SWAP[0,%d]: \"\n+\t\t\t\t\t\t\t\"0x%x\", pctype, reg);\n+\n+\t\t/**\n+\t\t * The offset and length read from register in word unit,\n+\t\t * which need to be converted in byte unit before being saved.\n+\t\t */\n+\t\tinfo->off0_src0 =\n+\t\t\t(uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC0_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_OFF0_SRC0_SHIFT) << 1;\n+\t\tinfo->off0_src1 =\n+\t\t\t(uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC1_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_OFF0_SRC1_SHIFT) << 1;\n+\t\tinfo->len0 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN0_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_FLEN0_SHIFT) << 1;\n+\t\tinfo->off1_src0 =\n+\t\t\t(uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC0_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_OFF1_SRC0_SHIFT) << 1;\n+\t\tinfo->off1_src1 =\n+\t\t\t(uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC1_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_OFF1_SRC1_SHIFT) << 1;\n+\t\tinfo->len1 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN1_MASK) >>\n+\t\t\t\t\tI40E_GLQF_SWAP_FLEN1_SHIFT) << 1;\n+\t\treturn 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"RSS type[%u] not supported\", info->flow_type);\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+/* Set filter swap configurations */\n+static int\n+i40e_set_filter_swap(struct i40e_hw *hw,\n+\t\t     const struct rte_eth_filter_swap_info *info)\n+{\n+\tuint32_t reg;\n+\tuint8_t pctype = i40e_flow_type_to_pctype(info->flow_type);\n+\n+\tif (pctype > 0) {\n+\t\tif (info->off0_src0 > I40E_SWAP_FIELD_OFFSET_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"off0_src0 (0x%x) exceeds the \"\n+\t\t\t\t\"maximum of 0x%x\", info->off0_src0,\n+\t\t\t\t\tI40E_SWAP_FIELD_OFFSET_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t} else if (info->off0_src1 > I40E_SWAP_FIELD_OFFSET_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"off0_src1 (0x%x) exceeds the \"\n+\t\t\t\t\"maximum of 0x%x\", info->off0_src1,\n+\t\t\t\t\tI40E_SWAP_FIELD_OFFSET_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t} else if (info->len0 > I40E_SWAP_FIELD_LEN_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"len0 (0x%x) exceeds the maximum \"\n+\t\t\t\"of 0x%x\", info->len0, I40E_SWAP_FIELD_LEN_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t} else if (info->off1_src0 > I40E_SWAP_FIELD_OFFSET_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"off1_src0 (0x%x) exceeds the \"\n+\t\t\t\t\"maximum of 0x%x\", info->off1_src0,\n+\t\t\t\t\tI40E_SWAP_FIELD_OFFSET_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t} else if (info->off1_src1 > I40E_SWAP_FIELD_OFFSET_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"off1_src1 (0x%x) exceeds the \"\n+\t\t\t\t\"maximum of 0x%x\", info->off1_src1,\n+\t\t\t\t\tI40E_SWAP_FIELD_OFFSET_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t} else if (info->len1 > I40E_SWAP_FIELD_LEN_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"len1 (0x%x) exceeds the maximum \"\n+\t\t\t\"of 0x%x\", info->len1, I40E_SWAP_FIELD_LEN_MAX);\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t}\n+\n+\t\t/**\n+\t\t * The offset and length given in byte unit, which need to be\n+\t\t * converted in word unit before being written to the register,\n+\t\t * as hardware requires it in word unit.\n+\t\t */\n+\t\treg = (info->off0_src0 >> 1) << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT;\n+\t\treg |= (info->off0_src1 >> 1) <<\n+\t\t\tI40E_GLQF_SWAP_OFF0_SRC1_SHIFT;\n+\t\treg |= (info->len0 >> 1) << I40E_GLQF_SWAP_FLEN0_SHIFT;\n+\t\treg |= (info->off1_src0 >> 1) <<\n+\t\t\tI40E_GLQF_SWAP_OFF1_SRC0_SHIFT;\n+\t\treg |= (info->off1_src1 >> 1) <<\n+\t\t\tI40E_GLQF_SWAP_OFF1_SRC1_SHIFT;\n+\t\treg |= (info->len1 >> 1) << I40E_GLQF_SWAP_FLEN1_SHIFT;\n+\n+\t\tPMD_DRV_LOG(DEBUG, \"Value to be written to \"\n+\t\t\t\"I40E_GLQF_SWAP[0,%d]: 0x%x\", pctype, reg);\n+\t\tI40E_WRITE_REG(hw, I40E_GLQF_SWAP(0, pctype), reg);\n+\t\tI40E_WRITE_FLUSH(hw);\n+\t\treturn 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"RSS type[%u] not supported\", info->flow_type);\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+/* Get hash function type */\n+static void\n+i40e_get_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function *hf)\n+{\n+\tuint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL);\n+\n+\tif (reg & I40E_GLQF_CTL_HTOEP_MASK)\n+\t\t*hf = RTE_ETH_HASH_FUNCTION_TOEPLITZ;\n+\telse\n+\t\t*hf = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;\n+\n+\tPMD_DRV_LOG(INFO, \"Hash function is %s\",\n+\t\t(reg & I40E_GLQF_CTL_HTOEP_MASK) ? \"Toeplitz\" : \"Simple XOR\");\n+}\n+\n+/* Set hash function type */\n+static int\n+i40e_set_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function hf)\n+{\n+\tuint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL);\n+\n+\tif (hf == RTE_ETH_HASH_FUNCTION_TOEPLITZ) {\n+\t\tif (reg & I40E_GLQF_CTL_HTOEP_MASK) {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"Hash function already set to \"\n+\t\t\t\t\t\t\t\t\"Toeplitz\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\treg |= I40E_GLQF_CTL_HTOEP_MASK;\n+\t} else if (hf == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {\n+\t\tif (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"Hash function already set to \"\n+\t\t\t\t\t\t\t\"Simple XOR\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\treg &= ~I40E_GLQF_CTL_HTOEP_MASK;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"Unknown hash function type\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tPMD_DRV_LOG(INFO, \"Hash function set to %s\",\n+\t\t(reg & I40E_GLQF_CTL_HTOEP_MASK) ? \"Toeplitz\" : \"Simple XOR\");\n+\tI40E_WRITE_REG(hw, I40E_GLQF_CTL, reg);\n+\tI40E_WRITE_FLUSH(hw);\n+\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info)\n+{\n+\tint ret = 0;\n+\n+\tif (!hw || !info) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid pointer\");\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tswitch (info->info_type) {\n+\tcase RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE:\n+\t\tret = i40e_get_symmetric_hash_enable_per_flow_type(hw,\n+\t\t\t\t\t&(info->info.sym_hash_ena));\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT:\n+\t\ti40e_get_symmetric_hash_enable_per_port(hw,\n+\t\t\t\t\t&(info->info.enable));\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_SWAP:\n+\t\tret = i40e_get_filter_swap(hw, &(info->info.filter_swap));\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_HASH_FUNCTION:\n+\t\ti40e_get_hash_function(hw, &(info->info.hash_function));\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Hash filter info type (%d) not supported\",\n+\t\t\t\t\t\t\tinfo->info_type);\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+i40e_hash_filter_set(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info)\n+{\n+\tint ret = 0;\n+\n+\tif (!hw || !info) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid pointer\");\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tswitch (info->info_type) {\n+\tcase RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE:\n+\t\tret = i40e_set_symmetric_hash_enable_per_flow_type(hw,\n+\t\t\t\t\t&(info->info.sym_hash_ena));\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT:\n+\t\ti40e_set_symmetric_hash_enable_per_port(hw, info->info.enable);\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_SWAP:\n+\t\tret = i40e_set_filter_swap(hw, &(info->info.filter_swap));\n+\t\tbreak;\n+\tcase RTE_ETH_HASH_FILTER_HASH_FUNCTION:\n+\t\tret = i40e_set_hash_function(hw, info->info.hash_function);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Hash filter info type (%d) not supported\",\n+\t\t\t\t\t\t\tinfo->info_type);\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* Operations for hash function */\n+static int\n+i40e_hash_filter_ctrl(struct rte_eth_dev *dev,\n+\t\t      enum rte_filter_op filter_op,\n+\t\t      void *arg)\n+{\n+\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint ret = 0;\n+\n+\tswitch (filter_op) {\n+\tcase RTE_ETH_FILTER_NOP:\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_GET:\n+\t\tret = i40e_hash_filter_get(hw,\n+\t\t\t(struct rte_eth_hash_filter_info *)arg);\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_SET:\n+\t\tret = i40e_hash_filter_set(hw,\n+\t\t\t(struct rte_eth_hash_filter_info *)arg);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(WARNING, \"Filter operation (%d) not supported\",\n+\t\t\t\t\t\t\t\tfilter_op);\n+\t\tret = -ENOTSUP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n static int\n i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n \t\t     enum rte_filter_type filter_type,\n@@ -5002,6 +5333,9 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n \t\treturn -EINVAL;\n \n \tswitch (filter_type) {\n+\tcase RTE_ETH_FILTER_HASH:\n+\t\tret = i40e_hash_filter_ctrl(dev, filter_op, arg);\n+\t\tbreak;\n \tcase RTE_ETH_FILTER_MACVLAN:\n \t\tret = i40e_mac_filter_handle(dev, filter_op, arg);\n \t\tbreak;\n@@ -5017,3 +5351,58 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n \n \treturn ret;\n }\n+\n+/*\n+ * As some registers wouldn't be reset unless a global hardware reset,\n+ * hardware initialization is needed to put those registers into an\n+ * expected initial state.\n+ */\n+static void\n+i40e_hw_init(struct i40e_hw *hw)\n+{\n+\t/* clear the PF Queue Filter control register */\n+\tI40E_WRITE_REG(hw, I40E_PFQF_CTL_0, 0);\n+\n+\t/* Disable symmetric hash per port */\n+\ti40e_set_symmetric_hash_enable_per_port(hw, 0);\n+}\n+\n+static uint8_t\n+i40e_flow_type_to_pctype(uint64_t type)\n+{\n+\tstruct flow_type_pctype_t {\n+\t\tuint8_t flow_type;\n+\t\tuint8_t pctype;\n+\t};\n+\tuint32_t i;\n+\tstatic const struct flow_type_pctype_t flow_type_pctype_table[] = {\n+\t\t{ETH_RSS_NONF_IPV4_UDP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_UDP},\n+\t\t{ETH_RSS_NONF_IPV4_TCP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_TCP},\n+\t\t{ETH_RSS_NONF_IPV4_SCTP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_SCTP},\n+\t\t{ETH_RSS_NONF_IPV4_OTHER_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_OTHER},\n+\t\t{ETH_RSS_FRAG_IPV4_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_FRAG_IPV4},\n+\t\t{ETH_RSS_NONF_IPV6_UDP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_UDP},\n+\t\t{ETH_RSS_NONF_IPV6_TCP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_TCP},\n+\t\t{ETH_RSS_NONF_IPV6_SCTP_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_SCTP},\n+\t\t{ETH_RSS_NONF_IPV6_OTHER_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_OTHER},\n+\t\t{ETH_RSS_FRAG_IPV6_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_FRAG_IPV6},\n+\t\t{ETH_RSS_L2_PAYLOAD_SHIFT,\n+\t\t\tI40E_FILTER_PCTYPE_L2_PAYLOAD}\n+\t};\n+\n+\tfor (i = 0; i < RTE_DIM(flow_type_pctype_table); i++)\n+\t\tif (type == flow_type_pctype_table[i].flow_type)\n+\t\t\treturn flow_type_pctype_table[i].pctype;\n+\n+\treturn 0;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "2/3"
    ]
}