From patchwork Mon Mar 9 08:24:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alvin Zhang X-Patchwork-Id: 66392 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 609ADA052E; Mon, 9 Mar 2020 09:31:13 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 82F6A1C0D1; Mon, 9 Mar 2020 09:29:26 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 03A9A1C0CE for ; Mon, 9 Mar 2020 09:29:23 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Mar 2020 01:29:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,518,1574150400"; d="scan'208";a="260350846" Received: from unknown (HELO dpdk-zhangalvin-dev.sh.intel.com) ([10.240.179.50]) by orsmga002.jf.intel.com with ESMTP; 09 Mar 2020 01:29:21 -0700 From: alvinx.zhang@intel.com To: dev@dpdk.org Cc: haiyue.wang@intel.com, xiaolong.ye@intel.com, qi.z.zhang@intel.com, beilei.xing@intel.com, Alvin Zhang Date: Mon, 9 Mar 2020 16:24:06 +0800 Message-Id: <1583742247-370386-14-git-send-email-alvinx.zhang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com> References: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com> Subject: [dpdk-dev] [PATCH v1 14/15] net/igc: implement hash filter configure X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Alvin Zhang Support configure of hash filter. Signed-off-by: Alvin Zhang --- drivers/net/igc/igc_filter.c | 155 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/igc/igc_txrx.c | 77 ++++++++++++++++++++- drivers/net/igc/igc_txrx.h | 4 ++ 3 files changed, 235 insertions(+), 1 deletion(-) diff --git a/drivers/net/igc/igc_filter.c b/drivers/net/igc/igc_filter.c index 5203d82..02f5720 100644 --- a/drivers/net/igc/igc_filter.c +++ b/drivers/net/igc/igc_filter.c @@ -670,6 +670,158 @@ return ret; } +/* + * Get global configurations of hash function type and symmetric hash enable + * per flow type (pctype). Note that global configuration means it affects all + * the ports on the same NIC. + */ +static int +igc_get_hash_filter_global_config(struct igc_hw *hw, + struct rte_eth_hash_global_conf *g_cfg) +{ + uint64_t rss_flowtype; + uint16_t i; + + memset(g_cfg, 0, sizeof(*g_cfg)); + g_cfg->hash_func = RTE_ETH_HASH_FUNCTION_DEFAULT; + + /* + * As igc supports less than 64 flow types, only first 64 bits need to + * be checked. + */ + for (i = 1; i < RTE_SYM_HASH_MASK_ARRAY_SIZE; i++) { + g_cfg->valid_bit_mask[i] = 0ULL; + g_cfg->sym_hash_enable_mask[i] = 0ULL; + } + + rss_flowtype = igc_get_rss_flowtype(hw); + g_cfg->valid_bit_mask[0] = rss_flowtype; + g_cfg->sym_hash_enable_mask[0] = rss_flowtype; + return 0; +} + +static int +igc_hash_filter_get(struct rte_eth_dev *dev, + struct rte_eth_hash_filter_info *info) +{ + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + uint32_t mrqc; + int ret = 0; + + if (!info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: + mrqc = IGC_READ_REG(hw, IGC_MRQC); + if ((mrqc & IGC_MRQC_ENABLE_MASK) == IGC_MRQC_ENABLE_RSS_4Q) + info->info.enable = 1; + else + info->info.enable = 0; + break; + case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: + ret = igc_get_hash_filter_global_config(hw, + &info->info.global_conf); + break; + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + } + + return ret; +} + +/* + * Set global configurations of hash function type and symmetric hash enable + * per flow type (pctype). Note any modifying global configuration will affect + * all the ports on the same NIC. + */ +static int +igc_set_hash_filter_global_config(struct igc_hw *hw, + struct rte_eth_hash_global_conf *g_cfg) +{ + uint64_t flow_type; + uint64_t mask; + + if (g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_DEFAULT) { + PMD_DRV_LOG(ERR, "function type %d not been supported!", + g_cfg->hash_func); + return -EINVAL; + } + + mask = g_cfg->valid_bit_mask[0] ^ g_cfg->sym_hash_enable_mask[0]; + + flow_type = igc_get_rss_flowtype(hw) & ~mask; + flow_type |= g_cfg->valid_bit_mask[0] & g_cfg->sym_hash_enable_mask[0]; + + igc_set_rss_flowtype(hw, flow_type); + return 0; +} + +static int +igc_hash_filter_set(struct rte_eth_dev *dev, + struct rte_eth_hash_filter_info *info) +{ + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + int ret = 0; + + if (!info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: + if (info->info.enable) + igc_rss_enable(dev); + else + igc_rss_disable(dev); + break; + case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: + ret = igc_set_hash_filter_global_config(hw, + &info->info.global_conf); + break; + + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + } + + return ret; +} + +/* Operations for hash function */ +static int +igc_hash_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + int ret = 0; + + switch (filter_op) { + case RTE_ETH_FILTER_NOP: + break; + case RTE_ETH_FILTER_GET: + ret = igc_hash_filter_get(dev, + (struct rte_eth_hash_filter_info *)arg); + break; + case RTE_ETH_FILTER_SET: + ret = igc_hash_filter_set(dev, + (struct rte_eth_hash_filter_info *)arg); + break; + default: + PMD_DRV_LOG(WARNING, "Filter operation (%d) not supported", + filter_op); + ret = -ENOTSUP; + } + + return ret; +} + void igc_clear_all_filter(struct rte_eth_dev *dev) { @@ -697,6 +849,9 @@ ret = igc_syn_filter_handle(dev, filter_op, (struct rte_eth_syn_filter *)arg); break; + case RTE_ETH_FILTER_HASH: + ret = igc_hash_filter_ctrl(dev, filter_op, arg); + break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type); diff --git a/drivers/net/igc/igc_txrx.c b/drivers/net/igc/igc_txrx.c index 9147fe8..217ecd2 100644 --- a/drivers/net/igc/igc_txrx.c +++ b/drivers/net/igc/igc_txrx.c @@ -835,7 +835,7 @@ int eth_igc_rx_descriptor_status(void *rx_queue, uint16_t offset) 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; -static void +void igc_rss_disable(struct rte_eth_dev *dev) { struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); @@ -847,6 +847,81 @@ int eth_igc_rx_descriptor_status(void *rx_queue, uint16_t offset) } void +igc_rss_enable(struct rte_eth_dev *dev) +{ + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + uint32_t mrqc; + + mrqc = IGC_READ_REG(hw, IGC_MRQC); + mrqc &= ~IGC_MRQC_ENABLE_MASK; + mrqc |= IGC_MRQC_ENABLE_RSS_4Q; + IGC_WRITE_REG(hw, IGC_MRQC, mrqc); +} + +uint64_t +igc_get_rss_flowtype(struct igc_hw *hw) +{ + uint64_t rss_flowtype = 0; + uint32_t mrqc; + + /* get RSS functions configured in MRQC register */ + mrqc = IGC_READ_REG(hw, IGC_MRQC); + + if (mrqc & IGC_MRQC_RSS_FIELD_IPV4) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_IPV4); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV4_TCP) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_IPV6); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6_EX) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_IPV6_EX); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6_TCP) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6_TCP_EX) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_IPV6_TCP_EX); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV4_UDP) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6_UDP) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP); + if (mrqc & IGC_MRQC_RSS_FIELD_IPV6_UDP_EX) + rss_flowtype |= (1ULL << RTE_ETH_FLOW_IPV6_UDP_EX); + + return rss_flowtype; +} + +void +igc_set_rss_flowtype(struct igc_hw *hw, uint64_t flowtype) +{ + uint32_t mrqc; + + /* get RSS functions configured in MRQC register */ + mrqc = IGC_READ_REG(hw, IGC_MRQC); + mrqc &= ~IGC_MRQC_RSS_FIELD_MASK; + + if (flowtype & (1ULL << RTE_ETH_FLOW_IPV4)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV4; + if (flowtype & (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV4_TCP; + if (flowtype & (1ULL << RTE_ETH_FLOW_IPV6)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6; + if (flowtype & (1ULL << RTE_ETH_FLOW_IPV6_EX)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_EX; + if (flowtype & (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_TCP; + if (flowtype & (1ULL << RTE_ETH_FLOW_IPV6_TCP_EX)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_TCP_EX; + if (flowtype & (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV4_UDP; + if (flowtype & (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP; + if (flowtype & (1ULL << RTE_ETH_FLOW_IPV6_UDP_EX)) + mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP_EX; + + IGC_WRITE_REG(hw, IGC_MRQC, mrqc); + IGC_WRITE_FLUSH(hw); +} + +void igc_hw_rss_hash_set(struct igc_hw *hw, struct rte_eth_rss_conf *rss_conf) { uint32_t *hash_key = (uint32_t *)rss_conf->rss_key; diff --git a/drivers/net/igc/igc_txrx.h b/drivers/net/igc/igc_txrx.h index df7b071..50be783 100644 --- a/drivers/net/igc/igc_txrx.h +++ b/drivers/net/igc/igc_txrx.h @@ -38,6 +38,10 @@ int eth_igc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, int igc_rx_init(struct rte_eth_dev *dev); void igc_tx_init(struct rte_eth_dev *dev); +void igc_rss_disable(struct rte_eth_dev *dev); +void igc_rss_enable(struct rte_eth_dev *dev); +uint64_t igc_get_rss_flowtype(struct igc_hw *hw); +void igc_set_rss_flowtype(struct igc_hw *hw, uint64_t flowtype); void igc_hw_rss_hash_set(struct igc_hw *hw, struct rte_eth_rss_conf *rss_conf); void eth_igc_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,