From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 3E03E7F95 for ; Wed, 19 Nov 2014 15:48:05 +0100 (CET) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 19 Nov 2014 06:58:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,417,1413270000"; d="scan'208";a="634549603" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by fmsmga002.fm.intel.com with ESMTP; 19 Nov 2014 06:58:28 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id sAJEwQF4032271; Wed, 19 Nov 2014 22:58:26 +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 sAJEwNkw001389; Wed, 19 Nov 2014 22:58:25 +0800 Received: (from hzhan75@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id sAJEwNEF001385; Wed, 19 Nov 2014 22:58:23 +0800 From: Helin Zhang 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> <1416409096-1340-1-git-send-email-helin.zhang@intel.com> Subject: [dpdk-dev] [PATCH v6 2/3] i40e: support of controlling hash functions 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, 19 Nov 2014 14:48:08 -0000 Hash filter control has been implemented for i40e. It includes getting/setting, - hash function type - symmetric hash enable per pctype (packet classification type) - symmetric hash enable per port - filter swap configuration Signed-off-by: Helin Zhang --- lib/librte_ether/rte_eth_ctrl.h | 98 +++++++++- lib/librte_pmd_i40e/i40e_ethdev.c | 389 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 482 insertions(+), 5 deletions(-) v5 changes: * Integrated with filter API defined recently. v6 changes: * Implemented the mapping function to convert RSS offload types to Packet Classification Types, to isolate the real hardware specific things. * Removed initialization of global registers in i40e PMD, as global registers shouldn't be initialized per port. * Added more annotations to get code more understandable. * Corrected annotation format for documenation. diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h index 8dd384d..1dab7d0 100644 --- a/lib/librte_ether/rte_eth_ctrl.h +++ b/lib/librte_ether/rte_eth_ctrl.h @@ -51,6 +51,7 @@ extern "C" { */ enum rte_filter_type { RTE_ETH_FILTER_NONE = 0, + RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_MACVLAN, RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_MAX @@ -60,29 +61,116 @@ enum rte_filter_type { * Generic operations on filters */ enum rte_filter_op { + /** used to check whether the type filter is supported */ RTE_ETH_FILTER_NOP = 0, - /**< used to check whether the type filter is supported */ RTE_ETH_FILTER_ADD, /**< add filter entry */ RTE_ETH_FILTER_UPDATE, /**< update filter entry */ RTE_ETH_FILTER_DELETE, /**< delete filter entry */ RTE_ETH_FILTER_FLUSH, /**< flush all entries */ RTE_ETH_FILTER_GET, /**< get filter entry */ RTE_ETH_FILTER_SET, /**< configurations */ + /** get information of filter, such as status or statistics */ RTE_ETH_FILTER_INFO, - /**< get information of filter, such as status or statistics */ RTE_ETH_FILTER_OP_MAX }; /** + * Hash filter information types. + * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE is for getting/setting the + * information/configuration of 'symmetric hash enable' per flow type. + * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT is for getting/setting the + * information/configuration of 'symmetric hash enable' per port. + * - RTE_ETH_HASH_FILTER_SWAP is for getting/setting the swap + * information/configuration which is for symmetric hash function. + * - RTE_ETH_HASH_FILTER_HASH_FUNCTION is for getting/setting the hash function + * which could be Toeplitz or Simple Xor. + */ +enum rte_eth_hash_filter_info_type { + RTE_ETH_HASH_FILTER_INFO_TYPE_UNKNOWN = 0, + /** Symmetric hash enable per flow type */ + RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE, + /** Symmetric hash enable per port */ + RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT, + /** Hash filter swap */ + RTE_ETH_HASH_FILTER_SWAP, + /** Hash function */ + RTE_ETH_HASH_FILTER_HASH_FUNCTION, + RTE_ETH_HASH_FILTER_INFO_TYPE_MAX, +}; + +/** + * Hash function types. + */ +enum rte_eth_hash_function { + RTE_ETH_HASH_FUNCTION_UNKNOWN = 0, + RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */ + RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */ + RTE_ETH_HASH_FUNCTION_MAX, +}; + +/** + * A structure used to set or get symmetric hash enable information, to support + * 'RTE_ETH_FILTER_HASH', 'RTE_ETH_FILTER_GET/RTE_ETH_FILTER_SET', with + * information type 'RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE'. + * The flow type could be 'ETH_RSS_<*>_SHIFT' which is defined in rte_ethdev.h. + */ +struct rte_eth_sym_hash_ena_info { + /** Flow type, defined in rte_ethdev.h */ + uint8_t flow_type; + uint8_t enable; /**< Enable or disable flag */ +}; + +/** + * A structure used to set or get filter swap information, to support + * 'RTE_ETH_FILTER_HASH', 'RTE_ETH_FILTER_GET/RTE_ETH_FILTER_SET', + * with information type 'RTE_ETH_HASH_FILTER_SWAP'. + * The flow type could be 'ETH_RSS_<*>_SHIFT' which is defined in rte_ethdev.h. + */ +struct rte_eth_filter_swap_info { + /** Flow type, defined in rte_ethdev.h */ + uint8_t flow_type; + /** Offset of the 1st field of the 1st couple to be swapped. */ + uint8_t off0_src0; + /** Offset of the 2nd field of the 1st couple to be swapped. */ + uint8_t off0_src1; + /** Field length of the first couple. */ + uint8_t len0; + /** Offset of the 1st field of the 2nd couple to be swapped. */ + uint8_t off1_src0; + /** Offset of the 2nd field of the 2nd couple to be swapped. */ + uint8_t off1_src1; + /** Field length of the second couple. */ + uint8_t len1; +}; + +/** + * A structure used to set or get hash filter information, to support filter + * type of 'RTE_ETH_FILTER_HASH' and its operations. + */ +struct rte_eth_hash_filter_info { + enum rte_eth_hash_filter_info_type info_type; /**< Information type. */ + /** Details of hash filter infomation */ + union { + /* For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE */ + struct rte_eth_sym_hash_ena_info sym_hash_ena; + /* For RTE_ETH_HASH_FILTER_SWAP */ + struct rte_eth_filter_swap_info filter_swap; + /* For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT */ + uint8_t enable; + /* For RTE_ETH_HASH_FILTER_HASH_FUNCTION */ + enum rte_eth_hash_function hash_function; + } info; +}; + +/* * MAC filter type */ enum rte_mac_filter_type { RTE_MAC_PERFECT_MATCH = 1, /**< exact match of MAC addr. */ - RTE_MACVLAN_PERFECT_MATCH, - /**< exact match of MAC addr and VLAN ID. */ + RTE_MACVLAN_PERFECT_MATCH, /**< exact match of MAC addr and VLAN ID. */ RTE_MAC_HASH_MATCH, /**< hash match of MAC addr. */ + /** hash match of MAC addr and exact match of VLAN ID. */ RTE_MACVLAN_HASH_MATCH, - /**< hash match of MAC addr and exact match of VLAN ID. */ }; /** diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index 9096802..4ec609b 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -99,6 +99,10 @@ #define I40E_PRE_TX_Q_CFG_WAIT_US 10 /* 10 us */ +/* Field max of swap configurations for symmetric hash */ +#define I40E_SWAP_FIELD_LEN_MAX 0x1F +#define I40E_SWAP_FIELD_OFFSET_MAX 0x7F + /* Mask of PF interrupt causes */ #define I40E_PFINT_ICR0_ENA_MASK ( \ I40E_PFINT_ICR0_ENA_ECC_ERR_MASK | \ @@ -209,6 +213,8 @@ static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); +static void i40e_hw_init(struct i40e_hw *hw); +static uint8_t i40e_flow_type_to_pctype(uint64_t type); static struct rte_pci_id pci_id_i40e_map[] = { #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, @@ -379,6 +385,9 @@ eth_i40e_dev_init(__rte_unused struct eth_driver *eth_drv, /* Make sure all is clean before doing PF reset */ i40e_clear_hw(hw); + /* Initialize the hardware */ + i40e_hw_init(hw); + /* Reset here to make sure all is clean for each PF */ ret = i40e_pf_reset(hw); if (ret) { @@ -4990,6 +4999,328 @@ i40e_pf_config_mq_rx(struct i40e_pf *pf) return ret; } +/* Get the symmetric hash enable configurations per flow type */ +static int +i40e_get_symmetric_hash_enable_per_flow_type(struct i40e_hw *hw, + struct rte_eth_sym_hash_ena_info *info) +{ + uint32_t reg; + uint8_t pctype = i40e_flow_type_to_pctype(info->flow_type); + + if (pctype > 0) { + reg = I40E_READ_REG(hw, I40E_GLQF_HSYM(pctype)); + info->enable = reg & I40E_GLQF_HSYM_SYMH_ENA_MASK ? 1 : 0; + return 0; + } else { + PMD_DRV_LOG(ERR, "RSS type[%u] not supported", info->flow_type); + return -EINVAL; + } +} + +/* Set the symmetric hash enable configurations per flow type */ +static int +i40e_set_symmetric_hash_enable_per_flow_type(struct i40e_hw *hw, + const struct rte_eth_sym_hash_ena_info *info) +{ + uint32_t reg; + uint8_t pctype = i40e_flow_type_to_pctype(info->flow_type); + + if (pctype > 0) { + reg = info->enable ? I40E_GLQF_HSYM_SYMH_ENA_MASK : 0; + I40E_WRITE_REG(hw, I40E_GLQF_HSYM(pctype), reg); + I40E_WRITE_FLUSH(hw); + return 0; + } else { + PMD_DRV_LOG(ERR, "RSS type[%u] not supported", info->flow_type); + return -EINVAL; + } +} + +/* Get the symmetric hash enable configurations per port */ +static void +i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable) +{ + uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); + + *enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0; +} + +/* Set the symmetric hash enable configurations per port */ +static void +i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable) +{ + uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); + + if (enable > 0) { + if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) { + PMD_DRV_LOG(INFO, "Symmetric hash has already " + "been enabled"); + return; + } + reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK; + } else { + if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) { + PMD_DRV_LOG(INFO, "Symmetric hash has already " + "been disabled"); + return; + } + reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK; + } + I40E_WRITE_REG(hw, I40E_PRTQF_CTL_0, reg); + I40E_WRITE_FLUSH(hw); +} + +/* Get filter swap configurations */ +static int +i40e_get_filter_swap(struct i40e_hw *hw, struct rte_eth_filter_swap_info *info) +{ + uint32_t reg; + uint8_t pctype = i40e_flow_type_to_pctype(info->flow_type); + + if (pctype > 0) { + reg = I40E_READ_REG(hw, I40E_GLQF_SWAP(0, pctype)); + PMD_DRV_LOG(DEBUG, "Value read from I40E_GLQF_SWAP[0,%d]: " + "0x%x", pctype, reg); + + /** + * The offset and length read from register in word unit, + * which need to be converted in byte unit before being saved. + */ + info->off0_src0 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC0_MASK) >> + I40E_GLQF_SWAP_OFF0_SRC0_SHIFT) << 1; + info->off0_src1 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC1_MASK) >> + I40E_GLQF_SWAP_OFF0_SRC1_SHIFT) << 1; + info->len0 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN0_MASK) >> + I40E_GLQF_SWAP_FLEN0_SHIFT) << 1; + info->off1_src0 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC0_MASK) >> + I40E_GLQF_SWAP_OFF1_SRC0_SHIFT) << 1; + info->off1_src1 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC1_MASK) >> + I40E_GLQF_SWAP_OFF1_SRC1_SHIFT) << 1; + info->len1 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN1_MASK) >> + I40E_GLQF_SWAP_FLEN1_SHIFT) << 1; + return 0; + } else { + PMD_DRV_LOG(ERR, "RSS type[%u] not supported", info->flow_type); + return -EINVAL; + } +} + +/* Set filter swap configurations */ +static int +i40e_set_filter_swap(struct i40e_hw *hw, + const struct rte_eth_filter_swap_info *info) +{ + uint32_t reg; + uint8_t pctype = i40e_flow_type_to_pctype(info->flow_type); + + if (pctype > 0) { + if (info->off0_src0 > I40E_SWAP_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off0_src0 (0x%x) exceeds the " + "maximum of 0x%x", info->off0_src0, + I40E_SWAP_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->off0_src1 > I40E_SWAP_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off0_src1 (0x%x) exceeds the " + "maximum of 0x%x", info->off0_src1, + I40E_SWAP_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->len0 > I40E_SWAP_FIELD_LEN_MAX) { + PMD_DRV_LOG(ERR, "len0 (0x%x) exceeds the maximum " + "of 0x%x", info->len0, I40E_SWAP_FIELD_LEN_MAX); + return I40E_ERR_PARAM; + } else if (info->off1_src0 > I40E_SWAP_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off1_src0 (0x%x) exceeds the " + "maximum of 0x%x", info->off1_src0, + I40E_SWAP_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->off1_src1 > I40E_SWAP_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off1_src1 (0x%x) exceeds the " + "maximum of 0x%x", info->off1_src1, + I40E_SWAP_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->len1 > I40E_SWAP_FIELD_LEN_MAX) { + PMD_DRV_LOG(ERR, "len1 (0x%x) exceeds the maximum " + "of 0x%x", info->len1, I40E_SWAP_FIELD_LEN_MAX); + return I40E_ERR_PARAM; + } + + /** + * The offset and length given in byte unit, which need to be + * converted in word unit before being written to the register, + * as hardware requires it in word unit. + */ + reg = (info->off0_src0 >> 1) << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT; + reg |= (info->off0_src1 >> 1) << + I40E_GLQF_SWAP_OFF0_SRC1_SHIFT; + reg |= (info->len0 >> 1) << I40E_GLQF_SWAP_FLEN0_SHIFT; + reg |= (info->off1_src0 >> 1) << + I40E_GLQF_SWAP_OFF1_SRC0_SHIFT; + reg |= (info->off1_src1 >> 1) << + I40E_GLQF_SWAP_OFF1_SRC1_SHIFT; + reg |= (info->len1 >> 1) << I40E_GLQF_SWAP_FLEN1_SHIFT; + + PMD_DRV_LOG(DEBUG, "Value to be written to " + "I40E_GLQF_SWAP[0,%d]: 0x%x", pctype, reg); + I40E_WRITE_REG(hw, I40E_GLQF_SWAP(0, pctype), reg); + I40E_WRITE_FLUSH(hw); + return 0; + } else { + PMD_DRV_LOG(ERR, "RSS type[%u] not supported", info->flow_type); + return -EINVAL; + } +} + +/* Get hash function type */ +static void +i40e_get_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function *hf) +{ + uint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL); + + if (reg & I40E_GLQF_CTL_HTOEP_MASK) + *hf = RTE_ETH_HASH_FUNCTION_TOEPLITZ; + else + *hf = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; + + PMD_DRV_LOG(INFO, "Hash function is %s", + (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); +} + +/* Set hash function type */ +static int +i40e_set_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function hf) +{ + uint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL); + + if (hf == RTE_ETH_HASH_FUNCTION_TOEPLITZ) { + if (reg & I40E_GLQF_CTL_HTOEP_MASK) { + PMD_DRV_LOG(DEBUG, "Hash function already set to " + "Toeplitz"); + return 0; + } + reg |= I40E_GLQF_CTL_HTOEP_MASK; + } else if (hf == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { + if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) { + PMD_DRV_LOG(DEBUG, "Hash function already set to " + "Simple XOR"); + return 0; + } + reg &= ~I40E_GLQF_CTL_HTOEP_MASK; + } else { + PMD_DRV_LOG(ERR, "Unknown hash function type"); + return -EINVAL; + } + + PMD_DRV_LOG(INFO, "Hash function set to %s", + (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); + I40E_WRITE_REG(hw, I40E_GLQF_CTL, reg); + I40E_WRITE_FLUSH(hw); + + return 0; +} + +static int +i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) +{ + int ret = 0; + + if (!hw || !info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE: + ret = i40e_get_symmetric_hash_enable_per_flow_type(hw, + &(info->info.sym_hash_ena)); + break; + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: + i40e_get_symmetric_hash_enable_per_port(hw, + &(info->info.enable)); + break; + case RTE_ETH_HASH_FILTER_SWAP: + ret = i40e_get_filter_swap(hw, &(info->info.filter_swap)); + break; + case RTE_ETH_HASH_FILTER_HASH_FUNCTION: + i40e_get_hash_function(hw, &(info->info.hash_function)); + break; + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + break; + } + + return ret; +} + +static int +i40e_hash_filter_set(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) +{ + int ret = 0; + + if (!hw || !info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_FLOW_TYPE: + ret = i40e_set_symmetric_hash_enable_per_flow_type(hw, + &(info->info.sym_hash_ena)); + break; + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: + i40e_set_symmetric_hash_enable_per_port(hw, info->info.enable); + break; + case RTE_ETH_HASH_FILTER_SWAP: + ret = i40e_set_filter_swap(hw, &(info->info.filter_swap)); + break; + case RTE_ETH_HASH_FILTER_HASH_FUNCTION: + ret = i40e_set_hash_function(hw, info->info.hash_function); + break; + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + break; + } + + return ret; +} + +/* Operations for hash function */ +static int +i40e_hash_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret = 0; + + switch (filter_op) { + case RTE_ETH_FILTER_NOP: + break; + case RTE_ETH_FILTER_GET: + ret = i40e_hash_filter_get(hw, + (struct rte_eth_hash_filter_info *)arg); + break; + case RTE_ETH_FILTER_SET: + ret = i40e_hash_filter_set(hw, + (struct rte_eth_hash_filter_info *)arg); + break; + default: + PMD_DRV_LOG(WARNING, "Filter operation (%d) not supported", + filter_op); + ret = -ENOTSUP; + break; + } + + return ret; +} + static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, @@ -5002,6 +5333,9 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev, return -EINVAL; switch (filter_type) { + case RTE_ETH_FILTER_HASH: + ret = i40e_hash_filter_ctrl(dev, filter_op, arg); + break; case RTE_ETH_FILTER_MACVLAN: ret = i40e_mac_filter_handle(dev, filter_op, arg); break; @@ -5017,3 +5351,58 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev, return ret; } + +/* + * As some registers wouldn't be reset unless a global hardware reset, + * hardware initialization is needed to put those registers into an + * expected initial state. + */ +static void +i40e_hw_init(struct i40e_hw *hw) +{ + /* clear the PF Queue Filter control register */ + I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, 0); + + /* Disable symmetric hash per port */ + i40e_set_symmetric_hash_enable_per_port(hw, 0); +} + +static uint8_t +i40e_flow_type_to_pctype(uint64_t type) +{ + struct flow_type_pctype_t { + uint8_t flow_type; + uint8_t pctype; + }; + uint32_t i; + static const struct flow_type_pctype_t flow_type_pctype_table[] = { + {ETH_RSS_NONF_IPV4_UDP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV4_UDP}, + {ETH_RSS_NONF_IPV4_TCP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV4_TCP}, + {ETH_RSS_NONF_IPV4_SCTP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV4_SCTP}, + {ETH_RSS_NONF_IPV4_OTHER_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV4_OTHER}, + {ETH_RSS_FRAG_IPV4_SHIFT, + I40E_FILTER_PCTYPE_FRAG_IPV4}, + {ETH_RSS_NONF_IPV6_UDP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV6_UDP}, + {ETH_RSS_NONF_IPV6_TCP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV6_TCP}, + {ETH_RSS_NONF_IPV6_SCTP_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV6_SCTP}, + {ETH_RSS_NONF_IPV6_OTHER_SHIFT, + I40E_FILTER_PCTYPE_NONF_IPV6_OTHER}, + {ETH_RSS_FRAG_IPV6_SHIFT, + I40E_FILTER_PCTYPE_FRAG_IPV6}, + {ETH_RSS_L2_PAYLOAD_SHIFT, + I40E_FILTER_PCTYPE_L2_PAYLOAD} + }; + + for (i = 0; i < RTE_DIM(flow_type_pctype_table); i++) + if (type == flow_type_pctype_table[i].flow_type) + return flow_type_pctype_table[i].pctype; + + return 0; +} -- 1.8.1.4