From patchwork Fri Oct 6 22:47:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412078 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 298E21CA82 for ; Fri, 6 Oct 2023 22:47:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ZEqwDaNs" Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6C45A6; Fri, 6 Oct 2023 15:47:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632466; x=1728168466; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=32akxHSYhb17D+XQtNXel6BwEp9EweKFmYRPZqxIveM=; b=ZEqwDaNsOutjV1XqFFzHvENYgerYgNubn0sOoORqGO+9W3rQfdXlPwUf aIKys78bnyt/o22DzMTh4N4V7Gu+wRUp7e1qNBjQqPFDQ9LAEy+P8H+Yo DfVaF8J4wkUoxsttak4FRntVrZfpUtH7f4fiqn5iOv/VOy52FqdyAL8cK 0i++hL0J43mHmfQgymaVajGrffNKYGGrOXKGv7FMvcKRO+9h7VkGBJWpR 34TW9Ycxl3/F556dCEzSzc9gwxRUBcJV+KSgZ6G72M3MWNm3GKeTKmfj4 FP7zwPN4bNZGd2RhxC1Q/H+2hz2z4djM3NK/m85kdEzEv5Be1kDfpUYiD Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="363201059" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="363201059" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610304" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610304" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:41 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Ahmed Zaki , Wojciech Drewek Subject: [PATCH net-next v2 1/6] net: ethtool: allow symmetric RSS hash for any flow type Date: Fri, 6 Oct 2023 16:47:21 -0600 Message-Id: <20231006224726.443836-2-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org Symmetric RSS hash functions are beneficial in applications that monitor both Tx and Rx packets of the same flow (IDS, software firewalls, ..etc). Getting all traffic of the same flow on the same RX queue results in higher CPU cache efficiency. Only fields that has counterparts in the other direction can be accepted; IP src/dst and L4 src/dst ports. The user may request RSS hash symmetry for a specific flow type, via: # ethtool -N|-U eth0 rx-flow-hash s|d|f|n symmetric or turn symmetry off (asymmetric) by: # ethtool -N|-U eth0 rx-flow-hash s|d|f|n Reviewed-by: Wojciech Drewek Signed-off-by: Ahmed Zaki --- Documentation/networking/scaling.rst | 6 ++++++ include/uapi/linux/ethtool.h | 1 + net/ethtool/ioctl.c | 11 +++++++++++ 3 files changed, 18 insertions(+) diff --git a/Documentation/networking/scaling.rst b/Documentation/networking/scaling.rst index 92c9fb46d6a2..64f3d7566407 100644 --- a/Documentation/networking/scaling.rst +++ b/Documentation/networking/scaling.rst @@ -44,6 +44,12 @@ by masking out the low order seven bits of the computed hash for the packet (usually a Toeplitz hash), taking this number as a key into the indirection table and reading the corresponding value. +Some NICs support symmetric RSS hashing where, if the IP (source address, +destination address) and TCP/UDP (source port, destination port) tuples +are swapped, the computed hash is the same. This is beneficial in some +applications that monitor TCP/IP flows (IDS, firewalls, ...etc) and need +both directions of the flow to land on the same Rx queue (and CPU). + Some advanced NICs allow steering packets to queues based on programmable filters. For example, webserver bound TCP port 80 packets can be directed to their own receive queue. Such “n-tuple” filters can diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index f7fba0dc87e5..bf67c8094ae0 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -2025,6 +2025,7 @@ static inline int ethtool_validate_duplex(__u8 duplex) #define RXH_IP_DST (1 << 5) #define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ #define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ +#define RXH_SYMMETRIC (1 << 30) #define RXH_DISCARD (1 << 31) #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 0b0ce4f81c01..44742653a4bd 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -980,6 +980,17 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, if (rc) return rc; + /* If a symmetric hash is requested, then: + * 1 - no other fields besides IP src/dst and/or L4 src/dst + * 2 - If src is set, dst must also be set + */ + if ((info.data & RXH_SYMMETRIC) && + ((info.data & ~(RXH_SYMMETRIC | RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) || + (!!(info.data & RXH_IP_SRC) ^ !!(info.data & RXH_IP_DST)) || + (!!(info.data & RXH_L4_B_0_1) ^ !!(info.data & RXH_L4_B_2_3)))) + return -EINVAL; + rc = dev->ethtool_ops->set_rxnfc(dev, &info); if (rc) return rc; From patchwork Fri Oct 6 22:47:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412079 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 119591CA82 for ; Fri, 6 Oct 2023 22:47:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="E2inWBDO" Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE388A6; Fri, 6 Oct 2023 15:47:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632471; x=1728168471; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NM9EE9HTl9rWpj1CsHsY211ttABfbYDKg9zIqN+1XE4=; b=E2inWBDOfiG2WIRuLW8sw9TWbSAUwmYRbpdXlmCZ5xpFv1gjswzfY2iI a+hgfX4d1acAPICz1mXlAK2BZA2touW140mGeXHeOv5U3w2zB9lhrh1SH 6XViHHs6OzdKkas26XdowcBkwWdIlbR0L6c3L9+gXGGZjdDUwK4cqFCJj K8zFr6W4DFdlIbNtGsz39UqrS7X03UqfPG13xS7WGkIZ8XRO36waYzB2N aAgaYeHPla/F3oHCD9B8g5MVqATC3Ze0F1+8shmysRwEvC9lSOrU3YPCS 6ct1PAe6OCSOE2TTfk2N7i73m9io7i/48vpPd9hgzACiwJCxiz40uHQbp A==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="363201091" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="363201091" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610336" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610336" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:46 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Ahmed Zaki , Wojciech Drewek Subject: [PATCH net-next v2 2/6] ice: fix ICE_AQ_VSI_Q_OPT_RSS_* register values Date: Fri, 6 Oct 2023 16:47:22 -0600 Message-Id: <20231006224726.443836-3-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org Fix the values of the ICE_AQ_VSI_Q_OPT_RSS_* registers. Shifting is already done when the values are used, no need to double shift. Bug was not discovered earlier since only ICE_AQ_VSI_Q_OPT_RSS_TPLZ (Zero) is currently used. Also, rename ICE_AQ_VSI_Q_OPT_RSS_XXX to ICE_AQ_VSI_Q_OPT_RSS_HASH_XXX for consistency. Fixes: 7bd527aa174f ("ice: Adjust naming for inner VLAN operations") Co-developed-by: Jesse Brandeburg Signed-off-by: Jesse Brandeburg Reviewed-by: Wojciech Drewek Signed-off-by: Ahmed Zaki --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 8 ++++---- drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++-- drivers/net/ethernet/intel/ice/ice_virtchnl.c | 12 +++++------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 51281b58ad72..56ec1897f4d8 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -491,10 +491,10 @@ struct ice_aqc_vsi_props { #define ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M (0xF << ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_S) #define ICE_AQ_VSI_Q_OPT_RSS_HASH_S 6 #define ICE_AQ_VSI_Q_OPT_RSS_HASH_M (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) -#define ICE_AQ_VSI_Q_OPT_RSS_TPLZ (0x0 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) -#define ICE_AQ_VSI_Q_OPT_RSS_SYM_TPLZ (0x1 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) -#define ICE_AQ_VSI_Q_OPT_RSS_XOR (0x2 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) -#define ICE_AQ_VSI_Q_OPT_RSS_JHASH (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) +#define ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ 0x0U +#define ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ 0x1U +#define ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR 0x2U +#define ICE_AQ_VSI_Q_OPT_RSS_HASH_JHASH 0x3U u8 q_opt_tc; #define ICE_AQ_VSI_Q_OPT_TC_OVR_S 0 #define ICE_AQ_VSI_Q_OPT_TC_OVR_M (0x1F << ICE_AQ_VSI_Q_OPT_TC_OVR_S) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index acc3ffc940e7..1adf65d88ef0 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1186,12 +1186,12 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) case ICE_VSI_PF: /* PF VSI will inherit RSS instance of PF */ lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; - hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; + hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; break; case ICE_VSI_VF: /* VF VSI will gets a small RSS table which is a VSI LUT type */ lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; - hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; + hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; break; default: dev_dbg(dev, "Unsupported VSI type %s\n", diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 01e88b6e43a1..55bf7891981f 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -823,8 +823,8 @@ static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) int status; lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; - hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_XOR : - ICE_AQ_VSI_Q_OPT_RSS_TPLZ; + hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR : + ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { @@ -832,11 +832,9 @@ static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) goto error_param; } - ctx->info.q_opt_rss = ((lut_type << - ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & - ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | - (hash_type & - ICE_AQ_VSI_Q_OPT_RSS_HASH_M); + ctx->info.q_opt_rss = + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_LUT_M, lut_type) | + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hash_type); /* Preserve existing queueing option setting */ ctx->info.q_opt_rss |= (vsi->info.q_opt_rss & From patchwork Fri Oct 6 22:47:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412080 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EE9E38F86 for ; Fri, 6 Oct 2023 22:48:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mPpA3Lv8" Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BEC7AAC; Fri, 6 Oct 2023 15:47:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632478; x=1728168478; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VmySA6M83X7Ihey8TyrNa3GmM9sJ5lDZSO/gb64Vn4A=; b=mPpA3Lv8DQzWn6F+tKaWFtIXOPu766C0rftZRHMl/BCDFRx7PEzgCo28 RFHS7bPBTy5wlc+IbRdxn04ksSZG3P3R2bpmH9Sc0F9TOOTw66OYkncSn ojJNsww1MBa4/ae8FYTSdLwj6pCe2BwYYR44M2Ug71h+3+UD4ybJpOrio I6mqN7XG+sxJJYl4BFmEoK7L4XRGa/Dg7/Hbs6wG504cIVx7aJ9zJIZG/ 3KL2P78OUwYOqoPjSs5h9XHDhEKcxD2Jq4BLWadxOYkjBQbZFaPq8pceg kNbvgoqn19fzLqREFeyXnZUEkucBOZwOMrqxuYIzWXsMNCjiUJnTrtVmk w==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="448044334" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="448044334" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610393" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610393" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:51 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Qi Zhang , Wojciech Drewek , Ahmed Zaki Subject: [PATCH net-next v2 3/6] ice: refactor RSS configuration Date: Fri, 6 Oct 2023 16:47:23 -0600 Message-Id: <20231006224726.443836-4-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Qi Zhang Refactor the driver to use a communication data structure for RSS config. To do so we introduce the new ice_rss_hash_cfg struct, and then pass it as an argument to several functions. Also introduce enum ice_rss_cfg_hdr_type to specify a more granular and flexible RSS configuration: ICE_RSS_OUTER_HEADERS - take outer layer as RSS input set ICE_RSS_INNER_HEADERS - take inner layer as RSS input set ICE_RSS_INNER_HEADERS_W_OUTER_IPV4 - take inner layer as RSS input set for packet with outer IPV4 ICE_RSS_INNER_HEADERS_W_OUTER_IPV6 - take inner layer as RSS input set for packet with outer IPV6 ICE_RSS_ANY_HEADERS - try with outer first then inner (same as the behaviour without this change) Finally, move the virtchnl_rss_algorithm enum to be with the other RSS related structures in the virtchnl.h file. There should be no functional change due to this patch. Reviewed-by: Wojciech Drewek Signed-off-by: Qi Zhang Co-developed-by: Jesse Brandeburg Signed-off-by: Jesse Brandeburg Co-developed-by: Ahmed Zaki Signed-off-by: Ahmed Zaki --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 6 +- drivers/net/ethernet/intel/ice/ice_flow.c | 232 +++++++++++------- drivers/net/ethernet/intel/ice/ice_flow.h | 33 ++- drivers/net/ethernet/intel/ice/ice_lib.c | 100 +++----- drivers/net/ethernet/intel/ice/ice_virtchnl.c | 36 +-- include/linux/avf/virtchnl.h | 16 +- 6 files changed, 246 insertions(+), 177 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index d3cb08e66dcb..d30d1b2a819b 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -2508,6 +2508,7 @@ static int ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) { struct ice_pf *pf = vsi->back; + struct ice_rss_hash_cfg cfg; struct device *dev; u64 hashed_flds; int status; @@ -2534,7 +2535,10 @@ ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) return -EINVAL; } - status = ice_add_rss_cfg(&pf->hw, vsi->idx, hashed_flds, hdrs); + cfg.hash_flds = hashed_flds; + cfg.addl_hdrs = hdrs; + cfg.hdr_type = ICE_RSS_ANY_HEADERS; + status = ice_add_rss_cfg(&pf->hw, vsi->idx, &cfg); if (status) { dev_dbg(dev, "ice_add_rss_cfg failed, vsi num = %d, error = %d\n", vsi->vsi_num, status); diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c index 85cca572c22a..ff76eaabfb69 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.c +++ b/drivers/net/ethernet/intel/ice/ice_flow.c @@ -1858,37 +1858,49 @@ int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id) /** * ice_flow_set_rss_seg_info - setup packet segments for RSS * @segs: pointer to the flow field segment(s) - * @hash_fields: fields to be hashed on for the segment(s) - * @flow_hdr: protocol header fields within a packet segment + * @seg_cnt: segment count + * @cfg: configure parameters * * Helper function to extract fields from hash bitmap and use flow * header value to set flow field segment for further use in flow * profile entry or removal. */ static int -ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, - u32 flow_hdr) +ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, + const struct ice_rss_hash_cfg *cfg) { + struct ice_flow_seg_info *seg; u64 val; - u8 i; + u16 i; + + /* set inner most segment */ + seg = &segs[seg_cnt - 1]; - for_each_set_bit(i, (unsigned long *)&hash_fields, - ICE_FLOW_FIELD_IDX_MAX) - ice_flow_set_fld(segs, (enum ice_flow_field)i, + for_each_set_bit(i, (const unsigned long *)&cfg->hash_flds, + (u16)ICE_FLOW_FIELD_IDX_MAX) + ice_flow_set_fld(seg, (enum ice_flow_field)i, ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, false); - ICE_FLOW_SET_HDRS(segs, flow_hdr); + ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); - if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & + /* set outer most header */ + if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) + segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | + ICE_FLOW_SEG_HDR_IPV_OTHER; + else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) + segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | + ICE_FLOW_SEG_HDR_IPV_OTHER; + + if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) return -EINVAL; - val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); + val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); if (val && !is_power_of_2(val)) return -EIO; - val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); + val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); if (val && !is_power_of_2(val)) return -EIO; @@ -1958,6 +1970,39 @@ int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) return status; } +/** + * ice_get_rss_hdr_type - get a RSS profile's header type + * @prof: RSS flow profile + */ +static enum ice_rss_cfg_hdr_type +ice_get_rss_hdr_type(struct ice_flow_prof *prof) +{ + if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { + return ICE_RSS_OUTER_HEADERS; + } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { + const struct ice_flow_seg_info *s; + + s = &prof->segs[ICE_RSS_OUTER_HEADERS]; + if (s->hdrs == ICE_FLOW_SEG_HDR_NONE) + return ICE_RSS_INNER_HEADERS; + if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4) + return ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; + if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6) + return ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; + } + + return ICE_RSS_ANY_HEADERS; +} + +static bool +ice_rss_match_prof(struct ice_rss_cfg *r, struct ice_flow_prof *prof, + enum ice_rss_cfg_hdr_type hdr_type) +{ + return (r->hash.hdr_type == hdr_type && + r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && + r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs); +} + /** * ice_rem_rss_list - remove RSS configuration from list * @hw: pointer to the hardware structure @@ -1969,15 +2014,16 @@ int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) static void ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) { + enum ice_rss_cfg_hdr_type hdr_type; struct ice_rss_cfg *r, *tmp; /* Search for RSS hash fields associated to the VSI that match the * hash configurations associated to the flow profile. If found * remove from the RSS entry list of the VSI context and delete entry. */ + hdr_type = ice_get_rss_hdr_type(prof); list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) - if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && - r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { + if (ice_rss_match_prof(r, prof, hdr_type)) { clear_bit(vsi_handle, r->vsis); if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { list_del(&r->l_entry); @@ -1998,11 +2044,12 @@ ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) static int ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) { + enum ice_rss_cfg_hdr_type hdr_type; struct ice_rss_cfg *r, *rss_cfg; + hdr_type = ice_get_rss_hdr_type(prof); list_for_each_entry(r, &hw->rss_list_head, l_entry) - if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && - r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { + if (ice_rss_match_prof(r, prof, hdr_type)) { set_bit(vsi_handle, r->vsis); return 0; } @@ -2012,8 +2059,9 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) if (!rss_cfg) return -ENOMEM; - rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; - rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; + rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match; + rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; + rss_cfg->hash.hdr_type = hdr_type; set_bit(vsi_handle, rss_cfg->vsis); list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head); @@ -2022,54 +2070,55 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) } #define ICE_FLOW_PROF_HASH_S 0 -#define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) +#define ICE_FLOW_PROF_HASH_M GENMASK_ULL(31, 0) #define ICE_FLOW_PROF_HDR_S 32 -#define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) -#define ICE_FLOW_PROF_ENCAP_S 63 -#define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) - -#define ICE_RSS_OUTER_HEADERS 1 -#define ICE_RSS_INNER_HEADERS 2 +#define ICE_FLOW_PROF_HDR_M GENMASK_ULL(61, 32) +#define ICE_FLOW_PROF_ENCAP_S 62 +#define ICE_FLOW_PROF_ENCAP_M GENMASK_ULL(63, 62) /* Flow profile ID format: * [0:31] - Packet match fields - * [32:62] - Protocol header - * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled + * [32:61] - Protocol header + * [62:63] - Encapsulation flag: + * 0 if non-tunneled + * 1 if tunneled + * 2 for tunneled with outer ipv4 + * 3 for tunneled with outer ipv6 */ -#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ - ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ +#define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ + ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ - ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))) + (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & \ + ICE_FLOW_PROF_ENCAP_M))) /** * ice_add_rss_cfg_sync - add an RSS configuration * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle - * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure - * @addl_hdrs: protocol header fields - * @segs_cnt: packet segment count + * @cfg: configure parameters * * Assumption: lock has already been acquired for RSS list */ static int -ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs, u8 segs_cnt) +ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg) { const enum ice_block blk = ICE_BLK_RSS; struct ice_flow_prof *prof = NULL; struct ice_flow_seg_info *segs; + u8 segs_cnt; int status; - if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX) - return -EINVAL; + segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? + ICE_FLOW_SEG_SINGLE : + ICE_FLOW_SEG_MAX; segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); if (!segs) return -ENOMEM; /* Construct the packet segment info from the hashed fields */ - status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, - addl_hdrs); + status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); if (status) goto exit; @@ -2123,9 +2172,9 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, * segment information. */ status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, - ICE_FLOW_GEN_PROFID(hashed_flds, + ICE_FLOW_GEN_PROFID(cfg->hash_flds, segs[segs_cnt - 1].hdrs, - segs_cnt), + cfg->hdr_type), segs, segs_cnt, &prof); if (status) goto exit; @@ -2150,29 +2199,37 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, * ice_add_rss_cfg - add an RSS configuration with specified hashed fields * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle - * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure - * @addl_hdrs: protocol header fields + * @cfg: configure parameters * * This function will generate a flow profile based on fields associated with * the input fields to hash on, the flow type and use the VSI number to add * a flow entry to the profile. */ int -ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs) +ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg) { + struct ice_rss_hash_cfg local_cfg; int status; - if (hashed_flds == ICE_HASH_INVALID || - !ice_is_vsi_valid(hw, vsi_handle)) + if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || + cfg->hdr_type > ICE_RSS_ANY_HEADERS || + cfg->hash_flds == ICE_HASH_INVALID) return -EINVAL; mutex_lock(&hw->rss_locks); - status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, - ICE_RSS_OUTER_HEADERS); - if (!status) - status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, - addl_hdrs, ICE_RSS_INNER_HEADERS); + local_cfg = *cfg; + if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { + status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); + } else { + local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; + status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); + if (!status) { + local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; + status = ice_add_rss_cfg_sync(hw, vsi_handle, + &local_cfg); + } + } mutex_unlock(&hw->rss_locks); return status; @@ -2182,28 +2239,29 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, * ice_rem_rss_cfg_sync - remove an existing RSS configuration * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle - * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove - * @addl_hdrs: Protocol header fields within a packet segment - * @segs_cnt: packet segment count + * @cfg: configure parameters * * Assumption: lock has already been acquired for RSS list */ static int -ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs, u8 segs_cnt) +ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg) { const enum ice_block blk = ICE_BLK_RSS; struct ice_flow_seg_info *segs; struct ice_flow_prof *prof; + u8 segs_cnt; int status; + segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? + ICE_FLOW_SEG_SINGLE : + ICE_FLOW_SEG_MAX; segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); if (!segs) return -ENOMEM; /* Construct the packet segment info from the hashed fields */ - status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, - addl_hdrs); + status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); if (status) goto out; @@ -2236,31 +2294,39 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle - * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove - * @addl_hdrs: Protocol header fields within a packet segment + * @cfg: configure parameters * * This function will lookup the flow profile based on the input * hash field bitmap, iterate through the profile entry list of * that profile and find entry associated with input VSI to be - * removed. Calls are made to underlying flow s which will APIs + * removed. Calls are made to underlying flow apis which will in * turn build or update buffers for RSS XLT1 section. */ -int __maybe_unused -ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs) +int +ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg) { + struct ice_rss_hash_cfg local_cfg; int status; - if (hashed_flds == ICE_HASH_INVALID || - !ice_is_vsi_valid(hw, vsi_handle)) + if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || + cfg->hdr_type > ICE_RSS_ANY_HEADERS || + cfg->hash_flds == ICE_HASH_INVALID) return -EINVAL; mutex_lock(&hw->rss_locks); - status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, - ICE_RSS_OUTER_HEADERS); - if (!status) - status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, - addl_hdrs, ICE_RSS_INNER_HEADERS); + local_cfg = *cfg; + if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { + status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); + } else { + local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; + status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); + if (!status) { + local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; + status = ice_rem_rss_cfg_sync(hw, vsi_handle, + &local_cfg); + } + } mutex_unlock(&hw->rss_locks); return status; @@ -2310,6 +2376,7 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, */ int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) { + struct ice_rss_hash_cfg hcfg; int status = 0; u64 hash_flds; @@ -2382,8 +2449,10 @@ int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) if (rss_hash == ICE_HASH_INVALID) return -EIO; - status = ice_add_rss_cfg(hw, vsi_handle, rss_hash, - ICE_FLOW_SEG_HDR_NONE); + hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; + hcfg.hash_flds = rss_hash; + hcfg.hdr_type = ICE_RSS_ANY_HEADERS; + status = ice_add_rss_cfg(hw, vsi_handle, &hcfg); if (status) break; } @@ -2407,16 +2476,7 @@ int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) mutex_lock(&hw->rss_locks); list_for_each_entry(r, &hw->rss_list_head, l_entry) { if (test_bit(vsi_handle, r->vsis)) { - status = ice_add_rss_cfg_sync(hw, vsi_handle, - r->hashed_flds, - r->packet_hdr, - ICE_RSS_OUTER_HEADERS); - if (status) - break; - status = ice_add_rss_cfg_sync(hw, vsi_handle, - r->hashed_flds, - r->packet_hdr, - ICE_RSS_INNER_HEADERS); + status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); if (status) break; } @@ -2447,8 +2507,8 @@ u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) mutex_lock(&hw->rss_locks); list_for_each_entry(r, &hw->rss_list_head, l_entry) if (test_bit(vsi_handle, r->vsis) && - r->packet_hdr == hdrs) { - rss_hash = r->hashed_flds; + r->hash.addl_hdrs == hdrs) { + rss_hash = r->hash.hash_flds; break; } mutex_unlock(&hw->rss_locks); diff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h index b465d27d9b80..7a1db1df760e 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.h +++ b/drivers/net/ethernet/intel/ice/ice_flow.h @@ -34,6 +34,8 @@ #define ICE_HASH_TCP_IPV6 (ICE_FLOW_HASH_IPV6 | ICE_FLOW_HASH_TCP_PORT) #define ICE_HASH_UDP_IPV4 (ICE_FLOW_HASH_IPV4 | ICE_FLOW_HASH_UDP_PORT) #define ICE_HASH_UDP_IPV6 (ICE_FLOW_HASH_IPV6 | ICE_FLOW_HASH_UDP_PORT) +#define ICE_HASH_SCTP_IPV4 (ICE_FLOW_HASH_IPV4 | ICE_FLOW_HASH_SCTP_PORT) +#define ICE_HASH_SCTP_IPV6 (ICE_FLOW_HASH_IPV6 | ICE_FLOW_HASH_SCTP_PORT) #define ICE_FLOW_HASH_GTP_TEID \ (BIT_ULL(ICE_FLOW_FIELD_IDX_GTPC_TEID)) @@ -279,6 +281,23 @@ enum ice_flow_avf_hdr_field { BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP)) +enum ice_rss_cfg_hdr_type { + ICE_RSS_OUTER_HEADERS, /* take outer headers as inputset. */ + ICE_RSS_INNER_HEADERS, /* take inner headers as inputset. */ + /* take inner headers as inputset for packet with outer ipv4. */ + ICE_RSS_INNER_HEADERS_W_OUTER_IPV4, + /* take inner headers as inputset for packet with outer ipv6. */ + ICE_RSS_INNER_HEADERS_W_OUTER_IPV6, + /* take outer headers first then inner headers as inputset */ + ICE_RSS_ANY_HEADERS +}; + +struct ice_rss_hash_cfg { + u32 addl_hdrs; /* protocol header fields */ + u64 hash_flds; /* hash bit field (ICE_FLOW_HASH_*) to configure */ + enum ice_rss_cfg_hdr_type hdr_type; /* to specify inner or outer */ +}; + enum ice_flow_dir { ICE_FLOW_RX = 0x02, }; @@ -289,6 +308,7 @@ enum ice_flow_priority { ICE_FLOW_PRIO_HIGH }; +#define ICE_FLOW_SEG_SINGLE 1 #define ICE_FLOW_SEG_MAX 2 #define ICE_FLOW_SEG_RAW_FLD_MAX 2 #define ICE_FLOW_FV_EXTRACT_SZ 2 @@ -381,8 +401,7 @@ struct ice_rss_cfg { struct list_head l_entry; /* bitmap of VSIs added to the RSS entry */ DECLARE_BITMAP(vsis, ICE_MAX_VSI); - u64 hashed_flds; - u32 packet_hdr; + struct ice_rss_hash_cfg hash; }; int @@ -406,11 +425,9 @@ void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle); int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle); int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds); int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle); -int -ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs); -int -ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, - u32 addl_hdrs); +int ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg); +int ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, + const struct ice_rss_hash_cfg *cfg); u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs); #endif /* _ICE_FLOW_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 1adf65d88ef0..b7c3ab0591c6 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1607,6 +1607,38 @@ static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi) vsi->vsi_num, status); } +static const struct ice_rss_hash_cfg default_rss_cfgs[] = { + /* configure RSS for IPv4 with input set IP src/dst */ + {ICE_FLOW_SEG_HDR_IPV4, ICE_FLOW_HASH_IPV4, ICE_RSS_ANY_HEADERS}, + /* configure RSS for IPv6 with input set IPv6 src/dst */ + {ICE_FLOW_SEG_HDR_IPV6, ICE_FLOW_HASH_IPV6, ICE_RSS_ANY_HEADERS}, + /* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */ + {ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4, + ICE_HASH_TCP_IPV4, ICE_RSS_ANY_HEADERS}, + /* configure RSS for udp4 with input set IP src/dst, UDP src/dst */ + {ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4, + ICE_HASH_UDP_IPV4, ICE_RSS_ANY_HEADERS}, + /* configure RSS for sctp4 with input set IP src/dst - only support + * RSS on SCTPv4 on outer headers (non-tunneled) + */ + {ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4, + ICE_HASH_SCTP_IPV4, ICE_RSS_OUTER_HEADERS}, + /* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */ + {ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6, + ICE_HASH_TCP_IPV6, ICE_RSS_ANY_HEADERS}, + /* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */ + {ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6, + ICE_HASH_UDP_IPV6, ICE_RSS_ANY_HEADERS}, + /* configure RSS for sctp6 with input set IPv6 src/dst - only support + * RSS on SCTPv6 on outer headers (non-tunneled) + */ + {ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6, + ICE_HASH_SCTP_IPV6, ICE_RSS_OUTER_HEADERS}, + /* configure RSS for IPSEC ESP SPI with input set MAC_IPV4_SPI */ + {ICE_FLOW_SEG_HDR_ESP, + ICE_FLOW_HASH_ESP_SPI, ICE_RSS_OUTER_HEADERS}, +}; + /** * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows * @vsi: VSI to be configured @@ -1625,6 +1657,7 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) struct ice_hw *hw = &pf->hw; struct device *dev; int status; + u32 i; dev = ice_pf_to_dev(pf); if (ice_is_safe_mode(pf)) { @@ -1632,67 +1665,14 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) vsi_num); return; } - /* configure RSS for IPv4 with input set IP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, - ICE_FLOW_SEG_HDR_IPV4); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for IPv6 with input set IPv6 src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, - ICE_FLOW_SEG_HDR_IPV6); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4, - ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %d\n", - vsi_num, status); + for (i = 0; i < ARRAY_SIZE(default_rss_cfgs); i++) { + const struct ice_rss_hash_cfg *cfg = &default_rss_cfgs[i]; - /* configure RSS for udp4 with input set IP src/dst, UDP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4, - ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for sctp4 with input set IP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, - ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6, - ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6, - ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %d\n", - vsi_num, status); - - /* configure RSS for sctp6 with input set IPv6 src/dst */ - status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, - ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %d\n", - vsi_num, status); - - status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_ESP_SPI, - ICE_FLOW_SEG_HDR_ESP); - if (status) - dev_dbg(dev, "ice_add_rss_cfg failed for esp/spi flow, vsi = %d, error = %d\n", - vsi_num, status); + status = ice_add_rss_cfg(hw, vsi_handle, cfg); + if (status) + dev_dbg(dev, "ice_add_rss_cfg failed, addl_hdrs = %x, hash_flds = %llx, hdr_type = %d\n", + cfg->addl_hdrs, cfg->hash_flds, cfg->hdr_type); + } } /** diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 55bf7891981f..f14aae2fe06c 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -689,9 +689,7 @@ ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto) * a specific virtchnl RSS cfg * @hw: pointer to the hardware * @rss_cfg: pointer to the virtchnl RSS cfg - * @addl_hdrs: pointer to the protocol header fields (ICE_FLOW_SEG_HDR_*) - * to configure - * @hash_flds: pointer to the hash bit fields (ICE_FLOW_HASH_*) to configure + * @hash_cfg: pointer to the HW hash configuration * * Return true if all the protocol header and hash fields in the RSS cfg could * be parsed, else return false @@ -699,13 +697,18 @@ ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto) * This function parses the virtchnl RSS cfg to be the intended * hash fields and the intended header for RSS configuration */ -static bool -ice_vc_parse_rss_cfg(struct ice_hw *hw, struct virtchnl_rss_cfg *rss_cfg, - u32 *addl_hdrs, u64 *hash_flds) +static bool ice_vc_parse_rss_cfg(struct ice_hw *hw, + struct virtchnl_rss_cfg *rss_cfg, + struct ice_rss_hash_cfg *hash_cfg) { const struct ice_vc_hash_field_match_type *hf_list; const struct ice_vc_hdr_match_type *hdr_list; int i, hf_list_len, hdr_list_len; + u32 *addl_hdrs = &hash_cfg->addl_hdrs; + u64 *hash_flds = &hash_cfg->hash_flds; + + /* set outer layer RSS as default */ + hash_cfg->hdr_type = ICE_RSS_OUTER_HEADERS; hf_list = ice_vc_hash_field_list; hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list); @@ -856,18 +859,24 @@ static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) kfree(ctx); } else { - u32 addl_hdrs = ICE_FLOW_SEG_HDR_NONE; - u64 hash_flds = ICE_HASH_INVALID; + struct ice_rss_hash_cfg cfg; + + /* Only check for none raw pattern case */ + if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + goto error_param; + } + cfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; + cfg.hash_flds = ICE_HASH_INVALID; + cfg.hdr_type = ICE_RSS_ANY_HEADERS; - if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &addl_hdrs, - &hash_flds)) { + if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &cfg)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } if (add) { - if (ice_add_rss_cfg(hw, vsi->idx, hash_flds, - addl_hdrs)) { + if (ice_add_rss_cfg(hw, vsi->idx, &cfg)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n", vsi->vsi_num, v_ret); @@ -875,8 +884,7 @@ static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) } else { int status; - status = ice_rem_rss_cfg(hw, vsi->idx, hash_flds, - addl_hdrs); + status = ice_rem_rss_cfg(hw, vsi->idx, &cfg); /* We just ignore -ENOENT, because if two configurations * share the same profile remove one of them actually * removes both, since the profile is deleted. diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h index dd71d3009771..a06f12d9f8d7 100644 --- a/include/linux/avf/virtchnl.h +++ b/include/linux/avf/virtchnl.h @@ -907,6 +907,14 @@ struct virtchnl_rss_hena { VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena); +/* Type of RSS algorithm */ +enum virtchnl_rss_algorithm { + VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC = 0, + VIRTCHNL_RSS_ALG_R_ASYMMETRIC = 1, + VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC = 2, + VIRTCHNL_RSS_ALG_XOR_SYMMETRIC = 3, +}; + /* VIRTCHNL_OP_ENABLE_CHANNELS * VIRTCHNL_OP_DISABLE_CHANNELS * VF sends these messages to enable or disable channels based on @@ -1091,14 +1099,6 @@ enum virtchnl_vfr_states { VIRTCHNL_VFR_VFACTIVE, }; -/* Type of RSS algorithm */ -enum virtchnl_rss_algorithm { - VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC = 0, - VIRTCHNL_RSS_ALG_R_ASYMMETRIC = 1, - VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC = 2, - VIRTCHNL_RSS_ALG_XOR_SYMMETRIC = 3, -}; - #define VIRTCHNL_MAX_NUM_PROTO_HDRS 32 #define PROTO_HDR_SHIFT 5 #define PROTO_HDR_FIELD_START(proto_hdr_type) ((proto_hdr_type) << PROTO_HDR_SHIFT) From patchwork Fri Oct 6 22:47:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412081 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46E5545F4A for ; Fri, 6 Oct 2023 22:48:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EbNyBKL7" Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 856F39C; Fri, 6 Oct 2023 15:48:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632482; x=1728168482; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=I3rOegVGbxcUy2S8NDVFJVbfIfe5oaqEs0oyUdHKVIw=; b=EbNyBKL76vXQjJ62satM8di686XuwI87hvx6HAzCwBlzBaOqJxuAujSw hzKLkfIpd3BjNrA5z3+P+Yt1mQafrSTDFzFQBsHqDx9biR7abYdiWxmfd zb5W+IPBpcfAhqBJx5oYlBlAJGlG7yzNGALwZiGSpBvjGSHZARZgx7zdA EeTEqil6meJ32Nj4Xp71gEwA2uw4mWqtHdio3Y50S4y97JIDY0VWZxTPr YWGrOqv2n5nU6pzuqYEyaoZO3bDeRGamFh62sJJHj8Hael70HEXL6RUPl UUXhKJBgaxnhxN9ak9RaxG/8qV0rrs4o4qsifDRv9Dt+/b3qLf7hao6in Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="448044370" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="448044370" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:48:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610498" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610498" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:47:57 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Ahmed Zaki , Dan Nowlin , Wojciech Drewek Subject: [PATCH net-next v2 4/6] ice: refactor the FD and RSS flow ID generation Date: Fri, 6 Oct 2023 16:47:24 -0600 Message-Id: <20231006224726.443836-5-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org The flow director and RSS blocks use separate methods to generate a unique 64 bit ID for the flow. This is not extendable, especially for the RSS that already uses all 64 bit space. Refactor the flow generation API so that the ID is generated within ice_flow_add_prof(). The FD and RSS blocks caches the generated ID for later use. Suggested-by: Dan Nowlin Reviewed-by: Wojciech Drewek Signed-off-by: Ahmed Zaki --- .../net/ethernet/intel/ice/ice_ethtool_fdir.c | 31 +++++------- .../net/ethernet/intel/ice/ice_flex_pipe.c | 10 ++++ .../net/ethernet/intel/ice/ice_flex_type.h | 6 +++ drivers/net/ethernet/intel/ice/ice_flow.c | 47 +++++-------------- drivers/net/ethernet/intel/ice/ice_flow.h | 2 +- drivers/net/ethernet/intel/ice/ice_main.c | 5 +- drivers/net/ethernet/intel/ice/ice_type.h | 1 + .../ethernet/intel/ice/ice_virtchnl_fdir.c | 33 ++++--------- 8 files changed, 54 insertions(+), 81 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c index 8c6e13f87b7d..c9c72f8dbcb2 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c @@ -302,9 +302,7 @@ void ice_fdir_rem_adq_chnl(struct ice_hw *hw, u16 vsi_idx) continue; for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) { - u64 prof_id; - - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; + u64 prof_id = prof->prof_id[tun]; for (i = 0; i < prof->cnt; i++) { if (prof->vsi_h[i] != vsi_idx) @@ -362,10 +360,9 @@ ice_fdir_erase_flow_from_hw(struct ice_hw *hw, enum ice_block blk, int flow) return; for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) { - u64 prof_id; + u64 prof_id = prof->prof_id[tun]; int j; - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; for (j = 0; j < prof->cnt; j++) { u16 vsi_num; @@ -439,12 +436,10 @@ void ice_fdir_replay_flows(struct ice_hw *hw) for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) { struct ice_flow_prof *hw_prof; struct ice_fd_hw_prof *prof; - u64 prof_id; int j; prof = hw->fdir_prof[flow]; - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; - ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id, + ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof->fdir_seg[tun], TNL_SEG_CNT(tun), &hw_prof); for (j = 0; j < prof->cnt; j++) { @@ -454,7 +449,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw) prio = ICE_FLOW_PRIO_NORMAL; err = ice_flow_add_entry(hw, ICE_BLK_FD, - prof_id, + hw_prof->id, prof->vsi_h[0], prof->vsi_h[j], prio, prof->fdir_seg, @@ -464,6 +459,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw) flow); continue; } + prof->prof_id[tun] = hw_prof->id; prof->entry_h[j][tun] = entry_h; } } @@ -630,7 +626,6 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, u64 entry1_h = 0; u64 entry2_h = 0; bool del_last; - u64 prof_id; int err; int idx; @@ -678,23 +673,23 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, * That is the final parameters are 1 header (segment), no * actions (NULL) and zero actions 0. */ - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; - err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id, seg, + err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg, TNL_SEG_CNT(tun), &prof); if (err) return err; - err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, main_vsi->idx, + err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx, main_vsi->idx, ICE_FLOW_PRIO_NORMAL, seg, &entry1_h); if (err) goto err_prof; - err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, main_vsi->idx, + err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx, ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL, seg, &entry2_h); if (err) goto err_entry; hw_prof->fdir_seg[tun] = seg; + hw_prof->prof_id[tun] = prof->id; hw_prof->entry_h[0][tun] = entry1_h; hw_prof->entry_h[1][tun] = entry2_h; hw_prof->vsi_h[0] = main_vsi->idx; @@ -711,7 +706,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, entry1_h = 0; vsi_h = main_vsi->tc_map_vsi[idx]->idx; - err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, + err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx, vsi_h, ICE_FLOW_PRIO_NORMAL, seg, &entry1_h); @@ -748,7 +743,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, if (!hw_prof->entry_h[idx][tun]) continue; - ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id); + ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof->id); ice_flow_rem_entry(hw, ICE_BLK_FD, hw_prof->entry_h[idx][tun]); hw_prof->entry_h[idx][tun] = 0; if (del_last) @@ -758,10 +753,10 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, hw_prof->cnt = 0; err_entry: ice_rem_prof_id_flow(hw, ICE_BLK_FD, - ice_get_hw_vsi_num(hw, main_vsi->idx), prof_id); + ice_get_hw_vsi_num(hw, main_vsi->idx), prof->id); ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h); err_prof: - ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id); + ice_flow_rem_prof(hw, ICE_BLK_FD, prof->id); dev_err(dev, "Failed to add filter. Flow director filters on each port must have the same input set.\n"); return err; diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c index 5ce413965930..41260110c29c 100644 --- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c +++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c @@ -2150,6 +2150,7 @@ void ice_clear_hw_tbls(struct ice_hw *hw) for (i = 0; i < ICE_BLK_COUNT; i++) { struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir; + struct ice_prof_id *prof_id = &hw->blk[i].prof_id; struct ice_prof_tcam *prof = &hw->blk[i].prof; struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1; struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2; @@ -2180,6 +2181,8 @@ void ice_clear_hw_tbls(struct ice_hw *hw) memset(es->ref_count, 0, es->count * sizeof(*es->ref_count)); memset(es->written, 0, es->count * sizeof(*es->written)); memset(es->mask_ena, 0, es->count * sizeof(*es->mask_ena)); + + memset(prof_id->id, 0, prof_id->count * sizeof(*prof_id->id)); } } @@ -2196,6 +2199,7 @@ int ice_init_hw_tbls(struct ice_hw *hw) ice_init_all_prof_masks(hw); for (i = 0; i < ICE_BLK_COUNT; i++) { struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir; + struct ice_prof_id *prof_id = &hw->blk[i].prof_id; struct ice_prof_tcam *prof = &hw->blk[i].prof; struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1; struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2; @@ -2301,6 +2305,12 @@ int ice_init_hw_tbls(struct ice_hw *hw) sizeof(*es->mask_ena), GFP_KERNEL); if (!es->mask_ena) goto err; + + prof_id->count = blk_sizes[i].prof_id; + prof_id->id = devm_kcalloc(ice_hw_to_dev(hw), prof_id->count, + sizeof(*prof_id->id), GFP_KERNEL); + if (!prof_id->id) + goto err; } return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_flex_type.h b/drivers/net/ethernet/intel/ice/ice_flex_type.h index 4f42e14ed3ae..395ebb18950a 100644 --- a/drivers/net/ethernet/intel/ice/ice_flex_type.h +++ b/drivers/net/ethernet/intel/ice/ice_flex_type.h @@ -304,10 +304,16 @@ struct ice_masks { struct ice_mask masks[ICE_PROF_MASK_COUNT]; }; +struct ice_prof_id { + unsigned long *id; + int count; +}; + /* Tables per block */ struct ice_blk_info { struct ice_xlt1 xlt1; struct ice_xlt2 xlt2; + struct ice_prof_id prof_id; struct ice_prof_tcam prof; struct ice_prof_redir prof_redir; struct ice_es es; diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c index ff76eaabfb69..44f90d243fe7 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.c +++ b/drivers/net/ethernet/intel/ice/ice_flow.c @@ -1329,7 +1329,6 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, * @hw: pointer to the HW struct * @blk: classification stage * @dir: flow direction - * @prof_id: unique ID to identify this flow profile * @segs: array of one or more packet segments that describe the flow * @segs_cnt: number of packet segments provided * @prof: stores the returned flow profile added @@ -1338,17 +1337,24 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, */ static int ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, - enum ice_flow_dir dir, u64 prof_id, + enum ice_flow_dir dir, struct ice_flow_seg_info *segs, u8 segs_cnt, struct ice_flow_prof **prof) { struct ice_flow_prof_params *params; + struct ice_prof_id *ids; int status; + u64 prof_id; u8 i; if (!prof) return -EINVAL; + ids = &hw->blk[blk].prof_id; + prof_id = find_first_zero_bit(ids->id, ids->count); + if (prof_id >= ids->count) + return -ENOSPC; + params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) return -ENOMEM; @@ -1394,6 +1400,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, INIT_LIST_HEAD(¶ms->prof->entries); mutex_init(¶ms->prof->entries_lock); + set_bit(prof_id, ids->id); *prof = params->prof; out: @@ -1437,6 +1444,7 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, /* Remove all hardware profiles associated with this flow profile */ status = ice_rem_prof(hw, blk, prof->id); if (!status) { + clear_bit(prof->id, hw->blk[blk].prof_id.id); list_del(&prof->l_entry); mutex_destroy(&prof->entries_lock); devm_kfree(ice_hw_to_dev(hw), prof); @@ -1512,14 +1520,13 @@ ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, * @hw: pointer to the HW struct * @blk: classification stage * @dir: flow direction - * @prof_id: unique ID to identify this flow profile * @segs: array of one or more packet segments that describe the flow * @segs_cnt: number of packet segments provided * @prof: stores the returned flow profile added */ int ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, - u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, + struct ice_flow_seg_info *segs, u8 segs_cnt, struct ice_flow_prof **prof) { int status; @@ -1539,8 +1546,7 @@ ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, mutex_lock(&hw->fl_profs_locks[blk]); - status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, - prof); + status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt, prof); if (!status) list_add(&(*prof)->l_entry, &hw->fl_profs[blk]); @@ -2069,28 +2075,6 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) return 0; } -#define ICE_FLOW_PROF_HASH_S 0 -#define ICE_FLOW_PROF_HASH_M GENMASK_ULL(31, 0) -#define ICE_FLOW_PROF_HDR_S 32 -#define ICE_FLOW_PROF_HDR_M GENMASK_ULL(61, 32) -#define ICE_FLOW_PROF_ENCAP_S 62 -#define ICE_FLOW_PROF_ENCAP_M GENMASK_ULL(63, 62) - -/* Flow profile ID format: - * [0:31] - Packet match fields - * [32:61] - Protocol header - * [62:63] - Encapsulation flag: - * 0 if non-tunneled - * 1 if tunneled - * 2 for tunneled with outer ipv4 - * 3 for tunneled with outer ipv6 - */ -#define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ - ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ - (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ - (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & \ - ICE_FLOW_PROF_ENCAP_M))) - /** * ice_add_rss_cfg_sync - add an RSS configuration * @hw: pointer to the hardware structure @@ -2168,13 +2152,8 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, goto exit; } - /* Create a new flow profile with generated profile and packet - * segment information. - */ + /* Create a new flow profile with packet segment information. */ status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, - ICE_FLOW_GEN_PROFID(cfg->hash_flds, - segs[segs_cnt - 1].hdrs, - cfg->hdr_type), segs, segs_cnt, &prof); if (status) goto exit; diff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h index 7a1db1df760e..73a54e1dd31f 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.h +++ b/drivers/net/ethernet/intel/ice/ice_flow.h @@ -406,7 +406,7 @@ struct ice_rss_cfg { int ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, - u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, + struct ice_flow_seg_info *segs, u8 segs_cnt, struct ice_flow_prof **prof); int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id); int diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index c726913bc635..20fb53ea4e5b 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -8117,13 +8117,12 @@ static int ice_add_vsi_to_fdir(struct ice_pf *pf, struct ice_vsi *vsi) for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) { enum ice_flow_priority prio; - u64 prof_id; /* add this VSI to FDir profile for this flow */ prio = ICE_FLOW_PRIO_NORMAL; prof = hw->fdir_prof[flow]; - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; - status = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, + status = ice_flow_add_entry(hw, ICE_BLK_FD, + prof->prof_id[tun], prof->vsi_h[0], vsi->idx, prio, prof->fdir_seg[tun], &entry_h); diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index bb5d8b681bc2..af468b2f1da6 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -245,6 +245,7 @@ struct ice_fd_hw_prof { int cnt; u64 entry_h[ICE_MAX_FDIR_VSI_PER_FILTER][ICE_FD_HW_SEG_MAX]; u16 vsi_h[ICE_MAX_FDIR_VSI_PER_FILTER]; + u64 prof_id[ICE_FD_HW_SEG_MAX]; }; /* Common HW capabilities for SW use */ diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c index daa6a1e894cf..5cd143863b21 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c @@ -10,19 +10,6 @@ #define to_fltr_conf_from_desc(p) \ container_of(p, struct virtchnl_fdir_fltr_conf, input) -#define ICE_FLOW_PROF_TYPE_S 0 -#define ICE_FLOW_PROF_TYPE_M (0xFFFFFFFFULL << ICE_FLOW_PROF_TYPE_S) -#define ICE_FLOW_PROF_VSI_S 32 -#define ICE_FLOW_PROF_VSI_M (0xFFFFFFFFULL << ICE_FLOW_PROF_VSI_S) - -/* Flow profile ID format: - * [0:31] - flow type, flow + tun_offs - * [32:63] - VSI index - */ -#define ICE_FLOW_PROF_FD(vsi, flow, tun_offs) \ - ((u64)(((((flow) + (tun_offs)) & ICE_FLOW_PROF_TYPE_M)) | \ - (((u64)(vsi) << ICE_FLOW_PROF_VSI_S) & ICE_FLOW_PROF_VSI_M))) - #define GTPU_TEID_OFFSET 4 #define GTPU_EH_QFI_OFFSET 1 #define GTPU_EH_QFI_MASK 0x3F @@ -493,6 +480,7 @@ ice_vc_fdir_rem_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, int tun) return; vf_prof = fdir->fdir_prof[flow]; + prof_id = vf_prof->prof_id[tun]; vf_vsi = ice_get_vf_vsi(vf); if (!vf_vsi) { @@ -503,9 +491,6 @@ ice_vc_fdir_rem_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, int tun) if (!fdir->prof_entry_cnt[flow][tun]) return; - prof_id = ICE_FLOW_PROF_FD(vf_vsi->vsi_num, - flow, tun ? ICE_FLTR_PTYPE_MAX : 0); - for (i = 0; i < fdir->prof_entry_cnt[flow][tun]; i++) if (vf_prof->entry_h[i][tun]) { u16 vsi_num = ice_get_hw_vsi_num(hw, vf_prof->vsi_h[i]); @@ -647,7 +632,6 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, struct ice_hw *hw; u64 entry1_h = 0; u64 entry2_h = 0; - u64 prof_id; int ret; pf = vf->pf; @@ -681,10 +665,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, ice_vc_fdir_rem_prof(vf, flow, tun); } - prof_id = ICE_FLOW_PROF_FD(vf_vsi->vsi_num, flow, - tun ? ICE_FLTR_PTYPE_MAX : 0); - - ret = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id, seg, + ret = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg, tun + 1, &prof); if (ret) { dev_dbg(dev, "Could not add VSI flow 0x%x for VF %d\n", @@ -692,7 +673,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, goto err_exit; } - ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, vf_vsi->idx, + ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx, vf_vsi->idx, ICE_FLOW_PRIO_NORMAL, seg, &entry1_h); if (ret) { @@ -701,7 +682,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, goto err_prof; } - ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, vf_vsi->idx, + ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx, ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL, seg, &entry2_h); if (ret) { @@ -725,14 +706,16 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, vf_prof->cnt++; fdir->prof_entry_cnt[flow][tun]++; + vf_prof->prof_id[tun] = prof->id; + return 0; err_entry_1: ice_rem_prof_id_flow(hw, ICE_BLK_FD, - ice_get_hw_vsi_num(hw, vf_vsi->idx), prof_id); + ice_get_hw_vsi_num(hw, vf_vsi->idx), prof->id); ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h); err_prof: - ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id); + ice_flow_rem_prof(hw, ICE_BLK_FD, prof->id); err_exit: return ret; } From patchwork Fri Oct 6 22:47:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412082 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53B4A37150 for ; Fri, 6 Oct 2023 22:48:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OaFCFWOH" Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6133A2; Fri, 6 Oct 2023 15:48:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632487; x=1728168487; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Y/6DhxHwRmP2bjeXmqDXX1HnDy7bCzcXSzLawl5omhQ=; b=OaFCFWOHQofMMpvpcJAozfmDyEwhYj/yDooz/RC4leR1qadfkjgjhi/R KpKrRPweGC3JEo/gDZFDelnjthvLa7PnSCqKWcaxP4a4ji20SRITW1n8N ZefM/5Ychh6eVYfEyrGry11nAopRNkCOV3v8jS+LEAiZXIZm/fbCOd8nN 3rV/ykjcekOn613JJzXh3j/O11ShRAnY4PQPMoZj0DLc2WFnDsbx9yh5V vaJzAHQ1eZ8FeAc6LZSJxZ2QaOIP6FLZyBrUZuJAzOwTuWzCb9s5mzoQP vw/2YJg3/EA23A+EWavo8JXUkj79139Z3TBQjHD4D8PM34xxZkzkK69rg A==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="448044399" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="448044399" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:48:07 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610574" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610574" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:48:02 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Jeff Guo , Wojciech Drewek , Ahmed Zaki Subject: [PATCH net-next v2 5/6] ice: enable symmetric RSS Toeplitz hash for any flow type Date: Fri, 6 Oct 2023 16:47:25 -0600 Message-Id: <20231006224726.443836-6-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Jeff Guo The hash function in the E800 NICs is set per-VSI and a specific AQ command is needed to modify the hash function. Use the AQ command to enable setting the symmetric Toeplitz RSS hash function for any VSI. When the Symmetric Toeplitz hash function is used, the hardware sets the input set of the RSS (Toeplitz) algorithm to be the XOR of the fields index by HSYMM and the fields index by the INSET registers. We use this to create a symmetric hash by setting the HSYMM registers to point to their counterparts in the INSET registers: HSYMM [src_fv] = dst_fv; HSYMM [dst_fv] = src_fv; where src_fv and dst_fv are the indexes of the protocol's src and dst fields. Reviewed-by: Wojciech Drewek Signed-off-by: Jeff Guo Signed-off-by: Jesse Brandeburg Co-developed-by: Ahmed Zaki Signed-off-by: Ahmed Zaki --- drivers/net/ethernet/intel/ice/ice.h | 2 + drivers/net/ethernet/intel/ice/ice_common.h | 1 + drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +- .../net/ethernet/intel/ice/ice_ethtool_fdir.c | 4 +- .../net/ethernet/intel/ice/ice_flex_pipe.c | 33 ++- .../net/ethernet/intel/ice/ice_flex_pipe.h | 4 +- .../net/ethernet/intel/ice/ice_flex_type.h | 1 + drivers/net/ethernet/intel/ice/ice_flow.c | 222 +++++++++++++++--- drivers/net/ethernet/intel/ice/ice_flow.h | 13 +- .../net/ethernet/intel/ice/ice_hw_autogen.h | 4 + drivers/net/ethernet/intel/ice/ice_lib.c | 41 ++-- drivers/net/ethernet/intel/ice/ice_main.c | 44 ++++ drivers/net/ethernet/intel/ice/ice_virtchnl.c | 9 +- .../ethernet/intel/ice/ice_virtchnl_fdir.c | 2 +- 14 files changed, 322 insertions(+), 68 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index fcaa5c3b8ec0..c131fe24f959 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -360,6 +360,7 @@ struct ice_vsi { /* RSS config */ u16 rss_table_size; /* HW RSS table size */ u16 rss_size; /* Allocated RSS queues */ + u8 rss_hfunc; /* User configured hash type */ u8 *rss_hkey_user; /* User configured hash keys */ u8 *rss_lut_user; /* User configured lookup table entries */ u8 rss_lut_type; /* used to configure Get/Set RSS LUT AQ call */ @@ -910,6 +911,7 @@ int ice_set_rss_lut(struct ice_vsi *vsi, u8 *lut, u16 lut_size); int ice_get_rss_lut(struct ice_vsi *vsi, u8 *lut, u16 lut_size); int ice_set_rss_key(struct ice_vsi *vsi, u8 *seed); int ice_get_rss_key(struct ice_vsi *vsi, u8 *seed); +int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc); void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size); int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset); void ice_print_link_msg(struct ice_vsi *vsi, bool isup); diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 31fdcac33986..8d08a34dfb65 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -6,6 +6,7 @@ #include +#include "ice.h" #include "ice_type.h" #include "ice_nvm.h" #include "ice_flex_pipe.h" diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index d30d1b2a819b..5ca959373f93 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -2538,7 +2538,9 @@ ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) cfg.hash_flds = hashed_flds; cfg.addl_hdrs = hdrs; cfg.hdr_type = ICE_RSS_ANY_HEADERS; - status = ice_add_rss_cfg(&pf->hw, vsi->idx, &cfg); + cfg.symm = !!(nfc->data & RXH_SYMMETRIC); + + status = ice_add_rss_cfg(&pf->hw, vsi, &cfg); if (status) { dev_dbg(dev, "ice_add_rss_cfg failed, vsi num = %d, error = %d\n", vsi->vsi_num, status); @@ -2559,6 +2561,7 @@ ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) struct ice_pf *pf = vsi->back; struct device *dev; u64 hash_flds; + bool symm; u32 hdrs; dev = ice_pf_to_dev(pf); @@ -2577,7 +2580,7 @@ ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) return; } - hash_flds = ice_get_rss_cfg(&pf->hw, vsi->idx, hdrs); + hash_flds = ice_get_rss_cfg(&pf->hw, vsi->idx, hdrs, &symm); if (hash_flds == ICE_HASH_INVALID) { dev_dbg(dev, "No hash fields found for the given header type, vsi num = %d\n", vsi->vsi_num); @@ -2601,6 +2604,9 @@ ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) hash_flds & ICE_FLOW_HASH_FLD_UDP_DST_PORT || hash_flds & ICE_FLOW_HASH_FLD_SCTP_DST_PORT) nfc->data |= (u64)RXH_L4_B_2_3; + + if (symm) + nfc->data |= (u64)RXH_SYMMETRIC; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c index c9c72f8dbcb2..20a2b768e2d8 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c @@ -441,7 +441,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw) prof = hw->fdir_prof[flow]; ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof->fdir_seg[tun], TNL_SEG_CNT(tun), - &hw_prof); + false, &hw_prof); for (j = 0; j < prof->cnt; j++) { enum ice_flow_priority prio; u64 entry_h = 0; @@ -674,7 +674,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg, * actions (NULL) and zero actions 0. */ err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg, - TNL_SEG_CNT(tun), &prof); + TNL_SEG_CNT(tun), false, &prof); if (err) return err; err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx, diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c index 41260110c29c..7f0bd4e42e40 100644 --- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c +++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c @@ -1218,11 +1218,13 @@ ice_prof_has_mask(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 *masks) * @blk: HW block * @fv: field vector to search for * @masks: masks for FV + * @symm: symmetric setting for RSS flows * @prof_id: receives the profile ID */ static int ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk, - struct ice_fv_word *fv, u16 *masks, u8 *prof_id) + struct ice_fv_word *fv, u16 *masks, bool symm, + u8 *prof_id) { struct ice_es *es = &hw->blk[blk].es; u8 i; @@ -1236,6 +1238,9 @@ ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk, for (i = 0; i < (u8)es->count; i++) { u16 off = i * es->fvw; + if (blk == ICE_BLK_RSS && es->symm[i] != symm) + continue; + if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv))) continue; @@ -1716,15 +1721,16 @@ ice_update_prof_masking(struct ice_hw *hw, enum ice_block blk, u16 prof_id, } /** - * ice_write_es - write an extraction sequence to hardware + * ice_write_es - write an extraction sequence and symmetric setting to hardware * @hw: pointer to the HW struct * @blk: the block in which to write the extraction sequence * @prof_id: the profile ID to write * @fv: pointer to the extraction sequence to write - NULL to clear extraction + * @symm: symmetric setting for RSS profiles */ static void ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, - struct ice_fv_word *fv) + struct ice_fv_word *fv, bool symm) { u16 off; @@ -1737,6 +1743,9 @@ ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, memcpy(&hw->blk[blk].es.t[off], fv, hw->blk[blk].es.fvw * sizeof(*fv)); } + + if (blk == ICE_BLK_RSS) + hw->blk[blk].es.symm[prof_id] = symm; } /** @@ -1753,7 +1762,7 @@ ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) if (hw->blk[blk].es.ref_count[prof_id] > 0) { if (!--hw->blk[blk].es.ref_count[prof_id]) { - ice_write_es(hw, blk, prof_id, NULL); + ice_write_es(hw, blk, prof_id, NULL, false); ice_free_prof_masks(hw, blk, prof_id); return ice_free_prof_id(hw, blk, prof_id); } @@ -2116,6 +2125,7 @@ void ice_free_hw_tbls(struct ice_hw *hw) devm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof_redir.t); devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.t); devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.ref_count); + devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.symm); devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.written); devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.mask_ena); } @@ -2179,6 +2189,7 @@ void ice_clear_hw_tbls(struct ice_hw *hw) memset(es->t, 0, es->count * sizeof(*es->t) * es->fvw); memset(es->ref_count, 0, es->count * sizeof(*es->ref_count)); + memset(es->symm, 0, es->count * sizeof(*es->symm)); memset(es->written, 0, es->count * sizeof(*es->written)); memset(es->mask_ena, 0, es->count * sizeof(*es->mask_ena)); @@ -2296,6 +2307,11 @@ int ice_init_hw_tbls(struct ice_hw *hw) if (!es->ref_count) goto err; + es->symm = devm_kcalloc(ice_hw_to_dev(hw), es->count, + sizeof(*es->symm), GFP_KERNEL); + if (!es->symm) + goto err; + es->written = devm_kcalloc(ice_hw_to_dev(hw), es->count, sizeof(*es->written), GFP_KERNEL); if (!es->written) @@ -2973,6 +2989,7 @@ ice_add_prof_attrib(struct ice_prof_map *prof, u8 ptg, u16 ptype, * @attr_cnt: number of elements in attr array * @es: extraction sequence (length of array is determined by the block) * @masks: mask for extraction sequence + * @symm: symmetric setting for RSS profiles * * This function registers a profile, which matches a set of PTYPES with a * particular extraction sequence. While the hardware profile is allocated @@ -2982,7 +2999,7 @@ ice_add_prof_attrib(struct ice_prof_map *prof, u8 ptg, u16 ptype, int ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], const struct ice_ptype_attributes *attr, u16 attr_cnt, - struct ice_fv_word *es, u16 *masks) + struct ice_fv_word *es, u16 *masks, bool symm) { u32 bytes = DIV_ROUND_UP(ICE_FLOW_PTYPE_MAX, BITS_PER_BYTE); DECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT); @@ -2996,7 +3013,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], mutex_lock(&hw->blk[blk].es.prof_map_lock); /* search for existing profile */ - status = ice_find_prof_id_with_mask(hw, blk, es, masks, &prof_id); + status = ice_find_prof_id_with_mask(hw, blk, es, masks, symm, &prof_id); if (status) { /* allocate profile ID */ status = ice_alloc_prof_id(hw, blk, &prof_id); @@ -3019,7 +3036,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], goto err_ice_add_prof; /* and write new es */ - ice_write_es(hw, blk, prof_id, es); + ice_write_es(hw, blk, prof_id, es, symm); } ice_prof_inc_ref(hw, blk, prof_id); @@ -3107,7 +3124,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], * This will search for a profile tracking ID which was previously added. * The profile map lock should be held before calling this function. */ -static struct ice_prof_map * +struct ice_prof_map * ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id) { struct ice_prof_map *entry = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h index 7af7c8e9aa4e..b39d7cdc381f 100644 --- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h +++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h @@ -42,7 +42,9 @@ bool ice_hw_ptype_ena(struct ice_hw *hw, u16 ptype); int ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], const struct ice_ptype_attributes *attr, u16 attr_cnt, - struct ice_fv_word *es, u16 *masks); + struct ice_fv_word *es, u16 *masks, bool symm); +struct ice_prof_map * +ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id); int ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl); int diff --git a/drivers/net/ethernet/intel/ice/ice_flex_type.h b/drivers/net/ethernet/intel/ice/ice_flex_type.h index 395ebb18950a..d427a79d001a 100644 --- a/drivers/net/ethernet/intel/ice/ice_flex_type.h +++ b/drivers/net/ethernet/intel/ice/ice_flex_type.h @@ -146,6 +146,7 @@ struct ice_es { u32 *mask_ena; struct list_head prof_map; struct ice_fv_word *t; + u8 *symm; /* symmetric setting per profile (RSS blk)*/ struct mutex prof_map_lock; /* protect access to profiles list */ u8 *written; u8 reverse; /* set to true to reverse FV order */ diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c index 44f90d243fe7..efce56368083 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.c +++ b/drivers/net/ethernet/intel/ice/ice_flow.c @@ -1235,6 +1235,7 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 +#define ICE_FLOW_FIND_PROF_CHK_SYMM 0x00000008 /** * ice_flow_find_prof_conds - Find a profile matching headers and conditions @@ -1243,13 +1244,14 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) * @dir: flow direction * @segs: array of one or more packet segments that describe the flow * @segs_cnt: number of packet segments provided + * @symm: symmetric setting for RSS profiles * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) */ static struct ice_flow_prof * ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, struct ice_flow_seg_info *segs, - u8 segs_cnt, u16 vsi_handle, u32 conds) + u8 segs_cnt, bool symm, u16 vsi_handle, u32 conds) { struct ice_flow_prof *p, *prof = NULL; @@ -1265,6 +1267,11 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, !test_bit(vsi_handle, p->vsis)) continue; + /* Check for symmetric settings */ + if ((conds & ICE_FLOW_FIND_PROF_CHK_SYMM) && + p->symm != symm) + continue; + /* Protocol headers must be checked. Matched fields are * checked if specified. */ @@ -1331,6 +1338,7 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, * @dir: flow direction * @segs: array of one or more packet segments that describe the flow * @segs_cnt: number of packet segments provided + * @symm: symmetric setting for RSS profiles * @prof: stores the returned flow profile added * * Assumption: the caller has acquired the lock to the profile list @@ -1339,7 +1347,7 @@ static int ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, struct ice_flow_seg_info *segs, u8 segs_cnt, - struct ice_flow_prof **prof) + bool symm, struct ice_flow_prof **prof) { struct ice_flow_prof_params *params; struct ice_prof_id *ids; @@ -1376,6 +1384,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, params->prof->id = prof_id; params->prof->dir = dir; params->prof->segs_cnt = segs_cnt; + params->prof->symm = symm; /* Make a copy of the segments that need to be persistent in the flow * profile instance @@ -1392,7 +1401,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, /* Add a HW profile for this flow profile */ status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes, params->attr, params->attr_cnt, params->es, - params->mask); + params->mask, symm); if (status) { ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); goto out; @@ -1522,12 +1531,13 @@ ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, * @dir: flow direction * @segs: array of one or more packet segments that describe the flow * @segs_cnt: number of packet segments provided + * @symm: symmetric setting for RSS profiles * @prof: stores the returned flow profile added */ int ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, struct ice_flow_seg_info *segs, u8 segs_cnt, - struct ice_flow_prof **prof) + bool symm, struct ice_flow_prof **prof) { int status; @@ -1546,7 +1556,8 @@ ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, mutex_lock(&hw->fl_profs_locks[blk]); - status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt, prof); + status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt, + symm, prof); if (!status) list_add(&(*prof)->l_entry, &hw->fl_profs[blk]); @@ -2068,6 +2079,7 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match; rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; rss_cfg->hash.hdr_type = hdr_type; + rss_cfg->hash.symm = prof->symm; set_bit(vsi_handle, rss_cfg->vsis); list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head); @@ -2075,6 +2087,139 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) return 0; } +/** + * ice_rss_config_xor_word - set the HSYMM registers for one input set word + * @hw: pointer to the hardware structure + * @prof_id: RSS hardware profile id + * @src: the FV index used by the protocol's source field + * @dst: the FV index used by the protocol's destination field + * + * Write to the HSYMM register with the index of @src FV the value of the @dst + * FV index. This will tell the hardware to XOR HSYMM[src] with INSET[dst] + * while calculating the RSS input set. + */ +static void +ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst) +{ + u32 val, reg, bits_shift; + u8 reg_idx; + + reg_idx = src / GLQF_HSYMM_REG_SIZE; + bits_shift = ((src % GLQF_HSYMM_REG_SIZE) << 3); + val = dst | GLQF_HSYMM_ENABLE_BIT; + + reg = rd32(hw, GLQF_HSYMM(prof_id, reg_idx)); + reg = (reg & ~(0xff << bits_shift)) | (val << bits_shift); + wr32(hw, GLQF_HSYMM(prof_id, reg_idx), reg); +} + +/** + * ice_rss_config_xor - set the symmetric registers for a profile's protocol + * @hw: pointer to the hardware structure + * @prof_id: RSS hardware profile id + * @src: the FV index used by the protocol's source field + * @dst: the FV index used by the protocol's destination field + * @len: length of the source/destination fields in words + */ +static void +ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len) +{ + int fv_last_word = + ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1; + int i; + + for (i = 0; i < len; i++) { + ice_rss_config_xor_word(hw, prof_id, + /* Yes, field vector in GLQF_HSYMM and + * GLQF_HINSET is inversed! + */ + fv_last_word - (src + i), + fv_last_word - (dst + i)); + ice_rss_config_xor_word(hw, prof_id, + fv_last_word - (dst + i), + fv_last_word - (src + i)); + } +} + +/** + * ice_rss_set_symm - set the symmetric settings for an RSS profile + * @hw: pointer to the hardware structure + * @prof: pointer to flow profile + * + * The symmetric hash will result from XORing the protocol's fields with + * indexes in GLQF_HSYMM and GLQF_HINSET. This function configures the profile's + * GLQF_HSYMM registers. + */ +static void ice_rss_set_symm(struct ice_hw *hw, struct ice_flow_prof *prof) +{ + struct ice_prof_map *map; + u8 prof_id, m; + + mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); + map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id); + if (map) + prof_id = map->prof_id; + mutex_unlock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); + + if (!map) + return; + + /* clear to default */ + for (m = 0; m < GLQF_HSYMM_REG_PER_PROF; m++) + wr32(hw, GLQF_HSYMM(prof_id, m), 0); + + if (prof->symm) { + struct ice_flow_seg_xtrct *ipv4_src, *ipv4_dst; + struct ice_flow_seg_xtrct *ipv6_src, *ipv6_dst; + struct ice_flow_seg_xtrct *sctp_src, *sctp_dst; + struct ice_flow_seg_xtrct *tcp_src, *tcp_dst; + struct ice_flow_seg_xtrct *udp_src, *udp_dst; + struct ice_flow_seg_info *seg; + + seg = &prof->segs[prof->segs_cnt - 1]; + + ipv4_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct; + ipv4_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct; + + ipv6_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct; + ipv6_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct; + + tcp_src = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct; + tcp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct; + + udp_src = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct; + udp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct; + + sctp_src = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct; + sctp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct; + + /* xor IPv4 */ + if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0) + ice_rss_config_xor(hw, prof_id, + ipv4_src->idx, ipv4_dst->idx, 2); + + /* xor IPv6 */ + if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0) + ice_rss_config_xor(hw, prof_id, + ipv6_src->idx, ipv6_dst->idx, 8); + + /* xor TCP */ + if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0) + ice_rss_config_xor(hw, prof_id, + tcp_src->idx, tcp_dst->idx, 1); + + /* xor UDP */ + if (udp_src->prot_id != 0 && udp_dst->prot_id != 0) + ice_rss_config_xor(hw, prof_id, + udp_src->idx, udp_dst->idx, 1); + + /* xor SCTP */ + if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0) + ice_rss_config_xor(hw, prof_id, + sctp_src->idx, sctp_dst->idx, 1); + } +} + /** * ice_add_rss_cfg_sync - add an RSS configuration * @hw: pointer to the hardware structure @@ -2094,8 +2239,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, int status; segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? - ICE_FLOW_SEG_SINGLE : - ICE_FLOW_SEG_MAX; + ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); if (!segs) @@ -2106,13 +2250,14 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, if (status) goto exit; - /* Search for a flow profile that has matching headers, hash fields - * and has the input VSI associated to it. If found, no further + /* Search for a flow profile that has matching headers, hash fields, + * symm and has the input VSI associated to it. If found, no further * operations required and exit. */ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, - vsi_handle, + cfg->symm, vsi_handle, ICE_FLOW_FIND_PROF_CHK_FLDS | + ICE_FLOW_FIND_PROF_CHK_SYMM | ICE_FLOW_FIND_PROF_CHK_VSI); if (prof) goto exit; @@ -2123,7 +2268,8 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, * the protocol header and new hash field configuration. */ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, - vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); + cfg->symm, vsi_handle, + ICE_FLOW_FIND_PROF_CHK_VSI); if (prof) { status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); if (!status) @@ -2139,11 +2285,12 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, } } - /* Search for a profile that has same match fields only. If this - * exists then associate the VSI to this profile. + /* Search for a profile that has the same match fields and symmetric + * setting. If this exists then associate the VSI to this profile. */ prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, - vsi_handle, + cfg->symm, vsi_handle, + ICE_FLOW_FIND_PROF_CHK_SYMM | ICE_FLOW_FIND_PROF_CHK_FLDS); if (prof) { status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); @@ -2154,10 +2301,12 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, /* Create a new flow profile with packet segment information. */ status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, - segs, segs_cnt, &prof); + segs, segs_cnt, cfg->symm, &prof); if (status) goto exit; + prof->symm = cfg->symm; + ice_rss_set_symm(hw, prof); status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); /* If association to a new flow profile failed then this profile can * be removed. @@ -2177,7 +2326,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, /** * ice_add_rss_cfg - add an RSS configuration with specified hashed fields * @hw: pointer to the hardware structure - * @vsi_handle: software VSI handle + * @vsi: VSI to add the RSS configuration to * @cfg: configure parameters * * This function will generate a flow profile based on fields associated with @@ -2185,14 +2334,19 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, * a flow entry to the profile. */ int -ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, +ice_add_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, const struct ice_rss_hash_cfg *cfg) { struct ice_rss_hash_cfg local_cfg; + u16 vsi_handle; int status; - if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || - cfg->hdr_type > ICE_RSS_ANY_HEADERS || + if (!vsi) + return -EINVAL; + + vsi_handle = vsi->idx; + if (!ice_is_vsi_valid(hw, vsi_handle) || + !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || cfg->hash_flds == ICE_HASH_INVALID) return -EINVAL; @@ -2211,6 +2365,11 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, } mutex_unlock(&hw->rss_locks); + /* Update the VSI's hash function */ + if (cfg->symm && vsi->rss_hfunc != ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ) + return ice_set_rss_hfunc(vsi, + ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ); + return status; } @@ -2233,8 +2392,7 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, int status; segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? - ICE_FLOW_SEG_SINGLE : - ICE_FLOW_SEG_MAX; + ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); if (!segs) return -ENOMEM; @@ -2245,7 +2403,7 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, goto out; prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, - vsi_handle, + cfg->symm, vsi_handle, ICE_FLOW_FIND_PROF_CHK_FLDS); if (!prof) { status = -ENOENT; @@ -2288,8 +2446,8 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, struct ice_rss_hash_cfg local_cfg; int status; - if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || - cfg->hdr_type > ICE_RSS_ANY_HEADERS || + if (!ice_is_vsi_valid(hw, vsi_handle) || + !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || cfg->hash_flds == ICE_HASH_INVALID) return -EINVAL; @@ -2346,19 +2504,24 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, /** * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver * @hw: pointer to the hardware structure - * @vsi_handle: software VSI handle + * @vsi: VF's VSI * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure * * This function will take the hash bitmap provided by the AVF driver via a * message, convert it to ICE-compatible values, and configure RSS flow * profiles. */ -int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) +int ice_add_avf_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, u64 avf_hash) { struct ice_rss_hash_cfg hcfg; + u16 vsi_handle; int status = 0; u64 hash_flds; + if (!vsi) + return -EINVAL; + + vsi_handle = vsi->idx; if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || !ice_is_vsi_valid(hw, vsi_handle)) return -EINVAL; @@ -2431,7 +2594,8 @@ int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; hcfg.hash_flds = rss_hash; hcfg.hdr_type = ICE_RSS_ANY_HEADERS; - status = ice_add_rss_cfg(hw, vsi_handle, &hcfg); + hcfg.symm = false; + status = ice_add_rss_cfg(hw, vsi, &hcfg); if (status) break; } @@ -2470,11 +2634,12 @@ int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle * @hdrs: protocol header type + * @symm: whether the RSS is symmetric (bool, output) * * This function will return the match fields of the first instance of flow * profile having the given header types and containing input VSI */ -u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) +u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm) { u64 rss_hash = ICE_HASH_INVALID; struct ice_rss_cfg *r; @@ -2488,6 +2653,7 @@ u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) if (test_bit(vsi_handle, r->vsis) && r->hash.addl_hdrs == hdrs) { rss_hash = r->hash.hash_flds; + *symm = r->hash.symm; break; } mutex_unlock(&hw->rss_locks); diff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h index 73a54e1dd31f..f0ac023ed37e 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.h +++ b/drivers/net/ethernet/intel/ice/ice_flow.h @@ -296,6 +296,7 @@ struct ice_rss_hash_cfg { u32 addl_hdrs; /* protocol header fields */ u64 hash_flds; /* hash bit field (ICE_FLOW_HASH_*) to configure */ enum ice_rss_cfg_hdr_type hdr_type; /* to specify inner or outer */ + bool symm; /* symmetric or asymmetric hash */ }; enum ice_flow_dir { @@ -311,6 +312,7 @@ enum ice_flow_priority { #define ICE_FLOW_SEG_SINGLE 1 #define ICE_FLOW_SEG_MAX 2 #define ICE_FLOW_SEG_RAW_FLD_MAX 2 +#define ICE_FLOW_SW_FIELD_VECTOR_MAX 48 #define ICE_FLOW_FV_EXTRACT_SZ 2 #define ICE_FLOW_SET_HDRS(seg, val) ((seg)->hdrs |= (u32)(val)) @@ -395,6 +397,8 @@ struct ice_flow_prof { /* software VSI handles referenced by this flow profile */ DECLARE_BITMAP(vsis, ICE_MAX_VSI); + + bool symm; /* Symmetric Hash for RSS */ }; struct ice_rss_cfg { @@ -407,7 +411,7 @@ struct ice_rss_cfg { int ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, struct ice_flow_seg_info *segs, u8 segs_cnt, - struct ice_flow_prof **prof); + bool symm, struct ice_flow_prof **prof); int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id); int ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, @@ -423,11 +427,12 @@ ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id); void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle); int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle); -int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds); +int ice_add_avf_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, + u64 hashed_flds); int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle); -int ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, +int ice_add_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, const struct ice_rss_hash_cfg *cfg); int ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, const struct ice_rss_hash_cfg *cfg); -u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs); +u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm); #endif /* _ICE_FLOW_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 6756f3d51d14..ac5aef1ea300 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -389,6 +389,10 @@ #define GLQF_HMASK_SEL(_i) (0x00410000 + ((_i) * 4)) #define GLQF_HMASK_SEL_MAX_INDEX 127 #define GLQF_HMASK_SEL_MASK_SEL_S 0 +#define GLQF_HSYMM(_i, _j) (0x0040F000 + ((_i) * 4 + (_j) * 512)) +#define GLQF_HSYMM_REG_SIZE 4 +#define GLQF_HSYMM_REG_PER_PROF 6 +#define GLQF_HSYMM_ENABLE_BIT BIT(7) #define PFQF_FD_ENA 0x0043A000 #define PFQF_FD_ENA_FD_ENA_M BIT(0) #define PFQF_FD_SIZE 0x00460100 diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index b7c3ab0591c6..048c0d80a0c9 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1186,12 +1186,10 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) case ICE_VSI_PF: /* PF VSI will inherit RSS instance of PF */ lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; - hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; break; case ICE_VSI_VF: /* VF VSI will gets a small RSS table which is a VSI LUT type */ lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; - hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; break; default: dev_dbg(dev, "Unsupported VSI type %s\n", @@ -1199,10 +1197,12 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) return; } - ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & - ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | - ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & - ICE_AQ_VSI_Q_OPT_RSS_HASH_M); + hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; + vsi->rss_hfunc = hash_type; + + ctxt->info.q_opt_rss = + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_LUT_M, lut_type) | + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hash_type); } static void @@ -1601,7 +1601,7 @@ static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi) return; } - status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA); + status = ice_add_avf_rss_cfg(&pf->hw, vsi, ICE_DEFAULT_RSS_HENA); if (status) dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %d\n", vsi->vsi_num, status); @@ -1609,34 +1609,34 @@ static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi) static const struct ice_rss_hash_cfg default_rss_cfgs[] = { /* configure RSS for IPv4 with input set IP src/dst */ - {ICE_FLOW_SEG_HDR_IPV4, ICE_FLOW_HASH_IPV4, ICE_RSS_ANY_HEADERS}, + {ICE_FLOW_SEG_HDR_IPV4, ICE_FLOW_HASH_IPV4, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for IPv6 with input set IPv6 src/dst */ - {ICE_FLOW_SEG_HDR_IPV6, ICE_FLOW_HASH_IPV6, ICE_RSS_ANY_HEADERS}, + {ICE_FLOW_SEG_HDR_IPV6, ICE_FLOW_HASH_IPV6, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */ {ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4, - ICE_HASH_TCP_IPV4, ICE_RSS_ANY_HEADERS}, + ICE_HASH_TCP_IPV4, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for udp4 with input set IP src/dst, UDP src/dst */ {ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4, - ICE_HASH_UDP_IPV4, ICE_RSS_ANY_HEADERS}, + ICE_HASH_UDP_IPV4, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for sctp4 with input set IP src/dst - only support * RSS on SCTPv4 on outer headers (non-tunneled) */ {ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4, - ICE_HASH_SCTP_IPV4, ICE_RSS_OUTER_HEADERS}, + ICE_HASH_SCTP_IPV4, ICE_RSS_OUTER_HEADERS, false}, /* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */ {ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6, - ICE_HASH_TCP_IPV6, ICE_RSS_ANY_HEADERS}, + ICE_HASH_TCP_IPV6, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */ {ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6, - ICE_HASH_UDP_IPV6, ICE_RSS_ANY_HEADERS}, + ICE_HASH_UDP_IPV6, ICE_RSS_ANY_HEADERS, false}, /* configure RSS for sctp6 with input set IPv6 src/dst - only support * RSS on SCTPv6 on outer headers (non-tunneled) */ {ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6, - ICE_HASH_SCTP_IPV6, ICE_RSS_OUTER_HEADERS}, + ICE_HASH_SCTP_IPV6, ICE_RSS_OUTER_HEADERS, false}, /* configure RSS for IPSEC ESP SPI with input set MAC_IPV4_SPI */ {ICE_FLOW_SEG_HDR_ESP, - ICE_FLOW_HASH_ESP_SPI, ICE_RSS_OUTER_HEADERS}, + ICE_FLOW_HASH_ESP_SPI, ICE_RSS_OUTER_HEADERS, false}, }; /** @@ -1652,7 +1652,7 @@ static const struct ice_rss_hash_cfg default_rss_cfgs[] = { */ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) { - u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num; + u16 vsi_num = vsi->vsi_num; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; struct device *dev; @@ -1668,10 +1668,11 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) for (i = 0; i < ARRAY_SIZE(default_rss_cfgs); i++) { const struct ice_rss_hash_cfg *cfg = &default_rss_cfgs[i]; - status = ice_add_rss_cfg(hw, vsi_handle, cfg); + status = ice_add_rss_cfg(hw, vsi, cfg); if (status) - dev_dbg(dev, "ice_add_rss_cfg failed, addl_hdrs = %x, hash_flds = %llx, hdr_type = %d\n", - cfg->addl_hdrs, cfg->hash_flds, cfg->hdr_type); + dev_dbg(dev, "ice_add_rss_cfg failed, addl_hdrs = %x, hash_flds = %llx, hdr_type = %d, symm = %d\n", + cfg->addl_hdrs, cfg->hash_flds, + cfg->hdr_type, cfg->symm); } } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 20fb53ea4e5b..437278a1ec0d 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -7682,6 +7682,50 @@ int ice_get_rss_key(struct ice_vsi *vsi, u8 *seed) return status; } +/** + * ice_set_rss_hfunc - Set RSS HASH function + * @vsi: Pointer to VSI structure + * @hfunc: hash function (ICE_AQ_VSI_Q_OPT_RSS_*) + * + * Returns 0 on success, negative on failure + */ +int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc) +{ + struct ice_vsi_ctx *ctx; + int err; + + if (hfunc == vsi->rss_hfunc) + return 0; + + if (hfunc != ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ && + hfunc != ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ) + return -EOPNOTSUPP; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); + ctx->info.q_opt_rss = vsi->info.q_opt_rss; + ctx->info.q_opt_rss &= ~ICE_AQ_VSI_Q_OPT_RSS_HASH_M; + ctx->info.q_opt_rss |= + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hfunc); + ctx->info.q_opt_tc = vsi->info.q_opt_tc; + ctx->info.q_opt_flags = vsi->info.q_opt_rss; + + err = ice_update_vsi(&vsi->back->hw, vsi->idx, ctx, NULL); + if (err) { + dev_err(ice_pf_to_dev(vsi->back), "Failed to configure RSS hash for VSI %d, error %d\n", + vsi->vsi_num, err); + } else { + vsi->info.q_opt_rss = ctx->info.q_opt_rss; + vsi->rss_hfunc = hfunc; + } + + kfree(ctx); + return err; +} + /** * ice_bridge_getlink - Get the hardware bridge mode * @skb: skb buff diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index f14aae2fe06c..1014679eb147 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -710,6 +710,11 @@ static bool ice_vc_parse_rss_cfg(struct ice_hw *hw, /* set outer layer RSS as default */ hash_cfg->hdr_type = ICE_RSS_OUTER_HEADERS; + if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) + hash_cfg->symm = true; + else + hash_cfg->symm = false; + hf_list = ice_vc_hash_field_list; hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list); hdr_list = ice_vc_hdr_list; @@ -876,7 +881,7 @@ static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) } if (add) { - if (ice_add_rss_cfg(hw, vsi->idx, &cfg)) { + if (ice_add_rss_cfg(hw, vsi, &cfg)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n", vsi->vsi_num, v_ret); @@ -2616,7 +2621,7 @@ static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg) } if (vrh->hena) { - status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, vrh->hena); + status = ice_add_avf_rss_cfg(&pf->hw, vsi, vrh->hena); v_ret = ice_err_to_virt_err(status); } diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c index 5cd143863b21..bcf5d85d5013 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c @@ -666,7 +666,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, } ret = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg, - tun + 1, &prof); + tun + 1, false, &prof); if (ret) { dev_dbg(dev, "Could not add VSI flow 0x%x for VF %d\n", flow, vf->vf_id); From patchwork Fri Oct 6 22:47:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Zaki X-Patchwork-Id: 13412083 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 299A83FB1B for ; Fri, 6 Oct 2023 22:48:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XUfySpTM" Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A527AD; Fri, 6 Oct 2023 15:48:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696632492; x=1728168492; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=V0oD1m7MvFUQ+AzSBLEPD+OD00w9gAK6X7Ab7JamBMo=; b=XUfySpTMXGnL2zn5zxAtEpLdg6pXpg1lov0MuIhBQC81UMA5ZmX9u/w7 gUYN09XpqNSgE0CKp1/B1d9VJcy1UDrPZsbLGiqRP1JF5FzcV5tHgfqfD bRj5mzfzu8WoUyaHfhjakvg3LBxJHqw6Do2VxafkSYSl7Rpsj9B2ie3We jQmTsryX9x4Y9zY8XJmnEgf0EwTV5GEfZWiHmLjZD9qSeVN3CNFmRqwEa cerdu8AIfaOtRU3W3fbpHH2cr79OOFaGppqnjKTEJl6y1mTv30X7LLKxz VwhtXpRyzHe3ZFbtrcmd9yimPPu28Tx3s5QiBm58b4yPJBImSNt85NoyH A==; X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="448044429" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="448044429" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:48:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10855"; a="1083610647" X-IronPort-AV: E=Sophos;i="6.03,204,1694761200"; d="scan'208";a="1083610647" Received: from dianaman-mobl1.ger.corp.intel.com (HELO azaki-desk1.intel.com) ([10.249.35.113]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2023 15:48:07 -0700 From: Ahmed Zaki To: netdev@vger.kernel.org Cc: intel-wired-lan@lists.osuosl.org, linux-doc@vger.kernel.org, corbet@lwn.net, jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, andrew@lunn.ch, horms@kernel.org, mkubecek@suse.cz, Ahmed Zaki , Madhu Chittim Subject: [PATCH net-next v2 6/6] iavf: enable symmetric RSS Toeplitz hash Date: Fri, 6 Oct 2023 16:47:26 -0600 Message-Id: <20231006224726.443836-7-ahmed.zaki@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006224726.443836-1-ahmed.zaki@intel.com> References: <20231006224726.443836-1-ahmed.zaki@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org Allow the VFs to support symmetric RSS for any flow type. The symmetric RSS will not be supported on PFs not advertising the ADV RSS Offload flag (ADV_RSS_SUPPORT()), for example the E700 series (i40e). Reviewed-by: Madhu Chittim Signed-off-by: Ahmed Zaki --- .../net/ethernet/intel/iavf/iavf_adv_rss.c | 8 +++++-- .../net/ethernet/intel/iavf/iavf_adv_rss.h | 3 ++- .../net/ethernet/intel/iavf/iavf_ethtool.c | 22 +++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_adv_rss.c b/drivers/net/ethernet/intel/iavf/iavf_adv_rss.c index 6edbf134b73f..a9e1da35e248 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_adv_rss.c +++ b/drivers/net/ethernet/intel/iavf/iavf_adv_rss.c @@ -95,17 +95,21 @@ iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds) * @rss_cfg: the virtchnl message to be filled with RSS configuration setting * @packet_hdrs: the RSS configuration protocol header types * @hash_flds: the RSS configuration protocol hash fields + * @symm: if true, symmetric hash is required * * Returns 0 if the RSS configuration virtchnl message is filled successfully */ int iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg, - u32 packet_hdrs, u64 hash_flds) + u32 packet_hdrs, u64 hash_flds, bool symm) { struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs; struct virtchnl_proto_hdr *hdr; - rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC; + if (symm) + rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC; + else + rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC; proto_hdrs->tunnel_level = 0; /* always outer layer */ diff --git a/drivers/net/ethernet/intel/iavf/iavf_adv_rss.h b/drivers/net/ethernet/intel/iavf/iavf_adv_rss.h index 4d3be11af7aa..e31eb2afebea 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_adv_rss.h +++ b/drivers/net/ethernet/intel/iavf/iavf_adv_rss.h @@ -80,13 +80,14 @@ struct iavf_adv_rss { u32 packet_hdrs; u64 hash_flds; + bool symm; struct virtchnl_rss_cfg cfg_msg; }; int iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg, - u32 packet_hdrs, u64 hash_flds); + u32 packet_hdrs, u64 hash_flds, bool symm); struct iavf_adv_rss * iavf_find_adv_rss_cfg_by_hdrs(struct iavf_adapter *adapter, u32 packet_hdrs); void diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c index 90397293525f..0eec30c390d6 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c @@ -1618,6 +1618,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter, struct iavf_adv_rss *rss_old, *rss_new; bool rss_new_add = false; int count = 50, err = 0; + bool symm = false; u64 hash_flds; u32 hdrs; @@ -1632,11 +1633,15 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter, if (hash_flds == IAVF_ADV_RSS_HASH_INVALID) return -EINVAL; + if (cmd->data & RXH_SYMMETRIC) + symm = true; + rss_new = kzalloc(sizeof(*rss_new), GFP_KERNEL); if (!rss_new) return -ENOMEM; - if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds)) { + if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds, + symm)) { kfree(rss_new); return -EINVAL; } @@ -1655,9 +1660,11 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter, if (rss_old) { if (rss_old->state != IAVF_ADV_RSS_ACTIVE) { err = -EBUSY; - } else if (rss_old->hash_flds != hash_flds) { + } else if (rss_old->hash_flds != hash_flds || + rss_old->symm != symm) { rss_old->state = IAVF_ADV_RSS_ADD_REQUEST; rss_old->hash_flds = hash_flds; + rss_old->symm = symm; memcpy(&rss_old->cfg_msg, &rss_new->cfg_msg, sizeof(rss_new->cfg_msg)); adapter->aq_required |= IAVF_FLAG_AQ_ADD_ADV_RSS_CFG; @@ -1669,6 +1676,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter, rss_new->state = IAVF_ADV_RSS_ADD_REQUEST; rss_new->packet_hdrs = hdrs; rss_new->hash_flds = hash_flds; + rss_new->symm = symm; list_add_tail(&rss_new->list, &adapter->adv_rss_list_head); adapter->aq_required |= IAVF_FLAG_AQ_ADD_ADV_RSS_CFG; } @@ -1698,6 +1706,7 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter, { struct iavf_adv_rss *rss; u64 hash_flds; + bool symm; u32 hdrs; if (!ADV_RSS_SUPPORT(adapter)) @@ -1711,10 +1720,12 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter, spin_lock_bh(&adapter->adv_rss_lock); rss = iavf_find_adv_rss_cfg_by_hdrs(adapter, hdrs); - if (rss) + if (rss) { hash_flds = rss->hash_flds; - else + symm = rss->symm; + } else { hash_flds = IAVF_ADV_RSS_HASH_INVALID; + } spin_unlock_bh(&adapter->adv_rss_lock); if (hash_flds == IAVF_ADV_RSS_HASH_INVALID) @@ -1738,6 +1749,9 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter, IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT)) cmd->data |= (u64)RXH_L4_B_2_3; + if (symm) + cmd->data |= (u64)RXH_SYMMETRIC; + return 0; }