[v3,09/18] net/bnxt: extend RSS hash support for P7 devices

Message ID 20231227042119.72469-10-ajit.khaparde@broadcom.com (mailing list archive)
State Accepted, archived
Delegated to: Ajit Khaparde
Headers
Series bnxt patchset |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Ajit Khaparde Dec. 27, 2023, 4:21 a.m. UTC
  P7 adapters support XOR based and checksum based RSS hashing.
Add support for checksum and XOR based RSS hash for these adapters.

Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Reviewed-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
 drivers/net/bnxt/bnxt.h        |  15 +--
 drivers/net/bnxt/bnxt_ethdev.c |  72 ++++++---------
 drivers/net/bnxt/bnxt_flow.c   |  37 +++++++-
 drivers/net/bnxt/bnxt_hwrm.c   |   6 ++
 drivers/net/bnxt/bnxt_reps.c   |   2 +-
 drivers/net/bnxt/bnxt_vnic.c   | 161 +++++++++++++++++++++++++++++++--
 drivers/net/bnxt/bnxt_vnic.h   |  18 +++-
 7 files changed, 242 insertions(+), 69 deletions(-)
  

Patch

diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index cd85a944e8..e7b288c849 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -638,15 +638,6 @@  struct bnxt_rep_info {
 #define BNXT_FW_STATUS_HEALTHY		0x8000
 #define BNXT_FW_STATUS_SHUTDOWN		0x100000
 
-#define BNXT_ETH_RSS_SUPPORT (	\
-	RTE_ETH_RSS_IPV4 |		\
-	RTE_ETH_RSS_NONFRAG_IPV4_TCP |	\
-	RTE_ETH_RSS_NONFRAG_IPV4_UDP |	\
-	RTE_ETH_RSS_IPV6 |		\
-	RTE_ETH_RSS_NONFRAG_IPV6_TCP |	\
-	RTE_ETH_RSS_NONFRAG_IPV6_UDP |	\
-	RTE_ETH_RSS_LEVEL_MASK)
-
 #define BNXT_HWRM_SHORT_REQ_LEN		sizeof(struct hwrm_short_input)
 
 struct bnxt_flow_stat_info {
@@ -815,7 +806,10 @@  struct bnxt {
 #define BNXT_VNIC_CAP_VLAN_RX_STRIP	BIT(3)
 #define BNXT_RX_VLAN_STRIP_EN(bp)	((bp)->vnic_cap_flags & BNXT_VNIC_CAP_VLAN_RX_STRIP)
 #define BNXT_VNIC_CAP_OUTER_RSS_TRUSTED_VF	BIT(4)
-#define BNXT_VNIC_CAP_L2_CQE_MODE		BIT(8)
+#define BNXT_VNIC_CAP_XOR_MODE		BIT(5)
+#define BNXT_VNIC_CAP_CHKSM_MODE	BIT(6)
+#define BNXT_VNIC_CAP_L2_CQE_MODE	BIT(8)
+
 	unsigned int		rx_nr_rings;
 	unsigned int		rx_cp_nr_rings;
 	unsigned int		rx_num_qs_per_vnic;
@@ -1176,4 +1170,5 @@  void bnxt_handle_vf_cfg_change(void *arg);
 int bnxt_flow_meter_ops_get(struct rte_eth_dev *eth_dev, void *arg);
 struct bnxt_vnic_info *bnxt_get_default_vnic(struct bnxt *bp);
 struct tf *bnxt_get_tfp_session(struct bnxt *bp, enum bnxt_session_type type);
+uint64_t bnxt_eth_rss_support(struct bnxt *bp);
 #endif
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 0f1c4326c4..ef5e65ff16 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -982,6 +982,25 @@  uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
 	return speed_capa;
 }
 
+uint64_t bnxt_eth_rss_support(struct bnxt *bp)
+{
+	uint64_t support;
+
+	support = RTE_ETH_RSS_IPV4 |
+		  RTE_ETH_RSS_NONFRAG_IPV4_TCP |
+		  RTE_ETH_RSS_NONFRAG_IPV4_UDP |
+		  RTE_ETH_RSS_IPV6 |
+		  RTE_ETH_RSS_NONFRAG_IPV6_TCP |
+		  RTE_ETH_RSS_NONFRAG_IPV6_UDP |
+		  RTE_ETH_RSS_LEVEL_MASK;
+
+	if (bp->vnic_cap_flags & BNXT_VNIC_CAP_CHKSM_MODE)
+		support |= (RTE_ETH_RSS_IPV4_CHKSUM |
+			    RTE_ETH_RSS_L4_CHKSUM);
+
+	return support;
+}
+
 static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
 				struct rte_eth_dev_info *dev_info)
 {
@@ -1023,7 +1042,7 @@  static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
 	dev_info->tx_queue_offload_capa = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
 	dev_info->tx_offload_capa = bnxt_get_tx_port_offloads(bp) |
 				    dev_info->tx_queue_offload_capa;
-	dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
+	dev_info->flow_type_rss_offloads = bnxt_eth_rss_support(bp);
 
 	dev_info->speed_capa = bnxt_get_speed_capabilities(bp);
 	dev_info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
@@ -2175,7 +2194,7 @@  static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
 		if (!rss_conf->rss_hf)
 			PMD_DRV_LOG(ERR, "Hash type NONE\n");
 	} else {
-		if (rss_conf->rss_hf & BNXT_ETH_RSS_SUPPORT)
+		if (rss_conf->rss_hf & bnxt_eth_rss_support(bp))
 			return -EINVAL;
 	}
 
@@ -2185,6 +2204,12 @@  static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
 	vnic->hash_mode =
 		bnxt_rte_to_hwrm_hash_level(bp, rss_conf->rss_hf,
 					    RTE_ETH_RSS_LEVEL(rss_conf->rss_hf));
+	rc = bnxt_rte_eth_to_hwrm_ring_select_mode(bp, rss_conf->rss_hf, vnic);
+	if (rc != 0)
+		return rc;
+
+	/* Cache the hash function */
+	bp->rss_conf.rss_hf = rss_conf->rss_hf;
 
 	/* Cache the hash function */
 	bp->rss_conf.rss_hf = rss_conf->rss_hf;
@@ -2218,60 +2243,21 @@  static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
 	struct bnxt *bp = eth_dev->data->dev_private;
 	struct bnxt_vnic_info *vnic = bnxt_get_default_vnic(bp);
 	int len, rc;
-	uint32_t hash_types;
 
 	rc = is_bnxt_in_error(bp);
 	if (rc)
 		return rc;
 
-	/* RSS configuration is the same for all VNICs */
+	/* Return the RSS configuration of the default VNIC. */
 	if (vnic && vnic->rss_hash_key) {
 		if (rss_conf->rss_key) {
 			len = rss_conf->rss_key_len <= HW_HASH_KEY_SIZE ?
 			      rss_conf->rss_key_len : HW_HASH_KEY_SIZE;
 			memcpy(rss_conf->rss_key, vnic->rss_hash_key, len);
 		}
-
-		hash_types = vnic->hash_type;
-		rss_conf->rss_hf = 0;
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_IPV4;
-			hash_types &= ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
-		}
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
-			hash_types &=
-				~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
-		}
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
-			hash_types &=
-				~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
-		}
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_IPV6;
-			hash_types &= ~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
-		}
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
-			hash_types &=
-				~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
-		}
-		if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6) {
-			rss_conf->rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
-			hash_types &=
-				~HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
-		}
-
+		bnxt_hwrm_rss_to_rte_hash_conf(vnic, &rss_conf->rss_hf);
 		rss_conf->rss_hf |=
 			bnxt_hwrm_to_rte_rss_level(bp, vnic->hash_mode);
-
-		if (hash_types) {
-			PMD_DRV_LOG(ERR,
-				"Unknown RSS config from firmware (%08x), RSS disabled",
-				vnic->hash_type);
-			return -ENOTSUP;
-		}
 	} else {
 		rss_conf->rss_hf = 0;
 	}
diff --git a/drivers/net/bnxt/bnxt_flow.c b/drivers/net/bnxt/bnxt_flow.c
index 15f0e1b308..2d707b48d2 100644
--- a/drivers/net/bnxt/bnxt_flow.c
+++ b/drivers/net/bnxt/bnxt_flow.c
@@ -881,6 +881,7 @@  static void bnxt_vnic_cleanup(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 	vnic->fw_grp_ids = NULL;
 
 	vnic->rx_queue_cnt = 0;
+	vnic->hash_type = 0;
 }
 
 static int bnxt_vnic_prep(struct bnxt *bp, struct bnxt_vnic_info *vnic,
@@ -1067,7 +1068,7 @@  bnxt_vnic_rss_cfg_update(struct bnxt *bp,
 {
 	const struct rte_flow_action_rss *rss;
 	unsigned int rss_idx, i, j, fw_idx;
-	uint16_t hash_type;
+	uint32_t hash_type;
 	uint64_t types;
 	int rc;
 
@@ -1115,9 +1116,9 @@  bnxt_vnic_rss_cfg_update(struct bnxt *bp,
 		}
 	}
 
-	/* Currently only Toeplitz hash is supported. */
-	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT &&
-	    rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ) {
+	if (BNXT_IS_HASH_FUNC_DEFAULT(rss->func) &&
+	    BNXT_IS_HASH_FUNC_TOEPLITZ(rss->func) &&
+	    BNXT_IS_HASH_FUNC_SIMPLE_XOR(bp, rss->func)) {
 		rte_flow_error_set(error,
 				   ENOTSUP,
 				   RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1175,6 +1176,34 @@  bnxt_vnic_rss_cfg_update(struct bnxt *bp,
 	vnic->hash_mode =
 		bnxt_rte_to_hwrm_hash_level(bp, rss->types, rss->level);
 
+	/* For P7 chips update the hash_type if hash_type not explicitly passed.
+	 * TODO: For P5 chips.
+	 */
+	if (BNXT_CHIP_P7(bp) &&
+	    vnic->hash_mode == BNXT_HASH_MODE_DEFAULT && !hash_type)
+		vnic->hash_type = HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
+
+	/* TODO:
+	 * hash will be performed on the L3 and L4 packet headers.
+	 * specific RSS hash types like IPv4-TCP etc... or L4-chksum or IPV4-chksum
+	 * will NOT have any bearing and will not be honored.
+	 * Check and reject flow create accordingly. TODO.
+	 */
+
+	rc = bnxt_rte_flow_to_hwrm_ring_select_mode(rss->func,
+						    rss->types,
+						    bp, vnic);
+	if (rc) {
+		rte_flow_error_set(error,
+				   ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_ACTION,
+				   act,
+				   "Unsupported RSS hash parameters");
+		rc = -rte_errno;
+		goto ret;
+	}
+
 	/* Update RSS key only if key_len != 0 */
 	if (rss->key_len != 0)
 		memcpy(vnic->rss_hash_key, rss->key, rss->key_len);
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index d649f217ec..587433a878 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -1025,6 +1025,12 @@  int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
 		PMD_DRV_LOG(DEBUG, "Rx VLAN strip capability enabled\n");
 	}
 
+	if (flags & HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RING_SELECT_MODE_XOR_CAP)
+		bp->vnic_cap_flags |= BNXT_VNIC_CAP_XOR_MODE;
+
+	if (flags & HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RING_SELECT_MODE_TOEPLITZ_CHKSM_CAP)
+		bp->vnic_cap_flags |= BNXT_VNIC_CAP_CHKSM_MODE;
+
 	bp->max_tpa_v2 = rte_le_to_cpu_16(resp->max_aggs_supported);
 
 	HWRM_UNLOCK();
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index 78337431af..d96d972904 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -569,7 +569,7 @@  int bnxt_rep_dev_info_get_op(struct rte_eth_dev *eth_dev,
 
 	dev_info->rx_offload_capa = bnxt_get_rx_port_offloads(parent_bp);
 	dev_info->tx_offload_capa = bnxt_get_tx_port_offloads(parent_bp);
-	dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
+	dev_info->flow_type_rss_offloads = bnxt_eth_rss_support(parent_bp);
 
 	dev_info->switch_info.name = eth_dev->device->name;
 	dev_info->switch_info.domain_id = rep_bp->switch_domain_id;
diff --git a/drivers/net/bnxt/bnxt_vnic.c b/drivers/net/bnxt/bnxt_vnic.c
index bf93120d28..6a57f85ea7 100644
--- a/drivers/net/bnxt/bnxt_vnic.c
+++ b/drivers/net/bnxt/bnxt_vnic.c
@@ -256,10 +256,15 @@  int bnxt_vnic_grp_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 	return 0;
 }
 
-uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
+uint32_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
 {
-	uint16_t hwrm_type = 0;
+	uint32_t hwrm_type = 0;
 
+	if (rte_type & RTE_ETH_RSS_IPV4_CHKSUM)
+		hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
+	if (rte_type & RTE_ETH_RSS_L4_CHKSUM)
+		hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
+			     HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
 	if ((rte_type & RTE_ETH_RSS_IPV4) ||
 	    (rte_type & RTE_ETH_RSS_ECPRI))
 		hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
@@ -273,6 +278,9 @@  uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
 		hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
 	if (rte_type & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
 		hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
+	if (rte_type & RTE_ETH_RSS_IPV4_CHKSUM)
+		hwrm_type |=
+			HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ_CHECKSUM;
 
 	return hwrm_type;
 }
@@ -287,6 +295,8 @@  int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp, uint64_t hash_f, uint32_t lvl)
 			     RTE_ETH_RSS_NONFRAG_IPV6_TCP));
 	bool l3_only = l3 && !l4;
 	bool l3_and_l4 = l3 && l4;
+	bool cksum = !!(hash_f &
+			(RTE_ETH_RSS_IPV4_CHKSUM | RTE_ETH_RSS_L4_CHKSUM));
 
 	/* If FW has not advertised capability to configure outer/inner
 	 * RSS hashing , just log a message. HW will work in default RSS mode.
@@ -302,12 +312,12 @@  int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp, uint64_t hash_f, uint32_t lvl)
 	switch (lvl) {
 	case BNXT_RSS_LEVEL_INNERMOST:
 		/* Irrespective of what RTE says, FW always does 4 tuple */
-		if (l3_and_l4 || l4 || l3_only)
+		if (l3_and_l4 || l4 || l3_only || cksum)
 			mode = BNXT_HASH_MODE_INNERMOST;
 		break;
 	case BNXT_RSS_LEVEL_OUTERMOST:
 		/* Irrespective of what RTE says, FW always does 4 tuple */
-		if (l3_and_l4 || l4 || l3_only)
+		if (l3_and_l4 || l4 || l3_only || cksum)
 			mode = BNXT_HASH_MODE_OUTERMOST;
 		break;
 	default:
@@ -733,6 +743,16 @@  bnxt_vnic_rss_create(struct bnxt *bp,
 		goto fail_cleanup;
 	}
 
+	/* Remove unsupported types */
+	rss_info->rss_types &= bnxt_eth_rss_support(bp);
+
+	/* If only unsupported type(s) are specified then quit */
+	if (rss_info->rss_types == 0) {
+		PMD_DRV_LOG(ERR,
+			    "Unsupported RSS hash type(s)\n");
+		goto fail_cleanup;
+	}
+
 	/* hwrm_type conversion */
 	vnic->hash_type = bnxt_rte_to_hwrm_hash_types(rss_info->rss_types);
 	vnic->hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss_info->rss_types,
@@ -803,9 +823,11 @@  bnxt_vnic_rss_hash_algo_update(struct bnxt *bp,
 			       struct bnxt_vnic_rss_info *rss_info)
 {
 	uint8_t old_rss_hash_key[HW_HASH_KEY_SIZE] = { 0 };
-	uint16_t	hash_type;
-	uint8_t		hash_mode;
+	uint32_t hash_type;
+	uint8_t hash_mode;
+	uint8_t ring_mode;
 	uint32_t apply = 0;
+	int rc;
 
 	/* validate key length */
 	if (rss_info->key_len != 0 && rss_info->key_len != HW_HASH_KEY_SIZE) {
@@ -815,12 +837,40 @@  bnxt_vnic_rss_hash_algo_update(struct bnxt *bp,
 		return -EINVAL;
 	}
 
+	/* Remove unsupported types */
+	rss_info->rss_types &= bnxt_eth_rss_support(bp);
+
+	/* If only unsupported type(s) are specified then quit */
+	if (!rss_info->rss_types) {
+		PMD_DRV_LOG(ERR,
+			    "Unsupported RSS hash type\n");
+		return -EINVAL;
+	}
+
 	/* hwrm_type conversion */
 	hash_type = bnxt_rte_to_hwrm_hash_types(rss_info->rss_types);
 	hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss_info->rss_types,
 						rss_info->rss_level);
+	ring_mode = vnic->ring_select_mode;
+
+	/* For P7 chips update the hash_type if hash_type not explicitly passed.
+	 * TODO: For P5 chips.
+	 */
+	if (BNXT_CHIP_P7(bp) &&
+	    hash_mode == BNXT_HASH_MODE_DEFAULT && !hash_type)
+		vnic->hash_type = HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
+
+	rc = bnxt_rte_flow_to_hwrm_ring_select_mode(rss_info->rss_func,
+						    rss_info->rss_types,
+						    bp,
+						    vnic);
+	if (rc)
+		return -EINVAL;
+
 	if (vnic->hash_mode != hash_mode ||
-	    vnic->hash_type != hash_type) {
+	    vnic->hash_type != hash_type ||
+	    vnic->ring_select_mode != ring_mode) {
 		apply = 1;
 		vnic->hash_mode = hash_mode;
 		vnic->hash_type = hash_type;
@@ -839,10 +889,10 @@  bnxt_vnic_rss_hash_algo_update(struct bnxt *bp,
 	if (apply) {
 		if (bnxt_hwrm_vnic_rss_cfg(bp, vnic)) {
 			memcpy(vnic->rss_hash_key, old_rss_hash_key, HW_HASH_KEY_SIZE);
-			BNXT_TF_DBG(ERR, "Error configuring vnic RSS config\n");
+			PMD_DRV_LOG(ERR, "Error configuring vnic RSS config\n");
 			return -EINVAL;
 		}
-		BNXT_TF_DBG(INFO, "Rss config successfully applied\n");
+		PMD_DRV_LOG(INFO, "Rss config successfully applied\n");
 	}
 	return 0;
 }
@@ -1245,3 +1295,96 @@  bnxt_get_default_vnic(struct bnxt *bp)
 {
 	return &bp->vnic_info[bp->vnic_queue_db.dflt_vnic_id];
 }
+
+uint8_t _bnxt_rte_to_hwrm_ring_select_mode(enum rte_eth_hash_function hash_f)
+{
+	/* If RTE_ETH_HASH_FUNCTION_DEFAULT || RTE_ETH_HASH_FUNCTION_TOEPLITZ */
+	uint8_t mode = HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ;
+
+	if (hash_f == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR)
+		mode = HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_XOR;
+
+	return mode;
+}
+
+int bnxt_rte_flow_to_hwrm_ring_select_mode(enum rte_eth_hash_function hash_f,
+					   uint64_t types, struct bnxt *bp,
+					   struct bnxt_vnic_info *vnic)
+{
+	if (hash_f != RTE_ETH_HASH_FUNCTION_TOEPLITZ &&
+	    hash_f != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+		if (hash_f == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ ||
+		    (!BNXT_CHIP_P7(bp) && hash_f == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR)) {
+			PMD_DRV_LOG(ERR, "Unsupported hash function\n");
+			return -ENOTSUP;
+		}
+	}
+
+	if (types & RTE_ETH_RSS_IPV4_CHKSUM || types & RTE_ETH_RSS_L4_CHKSUM) {
+		if ((bp->vnic_cap_flags & BNXT_VNIC_CAP_CHKSM_MODE) &&
+			(hash_f == RTE_ETH_HASH_FUNCTION_DEFAULT ||
+			 hash_f == RTE_ETH_HASH_FUNCTION_TOEPLITZ)) {
+			/* Checksum mode cannot with hash func makes no sense */
+			vnic->ring_select_mode =
+				HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ_CHECKSUM;
+			/* shadow copy types as !hash_f is always true with default func */
+			return 0;
+		}
+		PMD_DRV_LOG(ERR, "Hash function not supported with checksun type\n");
+		return -ENOTSUP;
+	}
+
+	vnic->ring_select_mode = _bnxt_rte_to_hwrm_ring_select_mode(hash_f);
+	return 0;
+}
+
+int bnxt_rte_eth_to_hwrm_ring_select_mode(struct bnxt *bp, uint64_t types,
+					  struct bnxt_vnic_info *vnic)
+{
+	/* If the config update comes via ethdev, there is no way to
+	 * specify anything for hash function.
+	 * So its either TOEPLITZ or the Checksum mode.
+	 * Note that checksum mode is not supported on older devices.
+	 */
+	if (types == RTE_ETH_RSS_IPV4_CHKSUM) {
+		if (bp->vnic_cap_flags & BNXT_VNIC_CAP_CHKSM_MODE)
+			vnic->ring_select_mode =
+			HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ_CHECKSUM;
+		else
+			return -ENOTSUP;
+	}
+
+	/* Older devices can support TOEPLITZ only.
+	 * Thor2 supports other hash functions, but can't change using this path.
+	 */
+	vnic->ring_select_mode =
+		HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ;
+	return 0;
+}
+
+void bnxt_hwrm_rss_to_rte_hash_conf(struct bnxt_vnic_info *vnic,
+				    uint64_t *rss_conf)
+{
+	uint32_t hash_types;
+
+	hash_types = vnic->hash_type;
+	*rss_conf = 0;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4)
+		*rss_conf |= RTE_ETH_RSS_IPV4;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4)
+		*rss_conf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4)
+		*rss_conf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6)
+		*rss_conf |= RTE_ETH_RSS_IPV6;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6)
+		*rss_conf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6)
+		*rss_conf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_AH_SPI_IPV6 ||
+	    hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_AH_SPI_IPV4)
+		*rss_conf |= RTE_ETH_RSS_AH;
+	if (hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_ESP_SPI_IPV6 ||
+	    hash_types & HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_ESP_SPI_IPV4)
+		*rss_conf |= RTE_ETH_RSS_ESP;
+}
diff --git a/drivers/net/bnxt/bnxt_vnic.h b/drivers/net/bnxt/bnxt_vnic.h
index 7a6a0aa739..d01c9ebdb4 100644
--- a/drivers/net/bnxt/bnxt_vnic.h
+++ b/drivers/net/bnxt/bnxt_vnic.h
@@ -31,6 +31,11 @@ 
 	 (BNXT_VF(bp) && BNXT_VF_IS_TRUSTED(bp) &&				\
 	  !((bp)->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS_TRUSTED_VF)) ||	\
 	 (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp)))
+#define BNXT_IS_HASH_FUNC_DEFAULT(f)	((f) != RTE_ETH_HASH_FUNCTION_DEFAULT)
+#define BNXT_IS_HASH_FUNC_TOEPLITZ(f)	((f) != RTE_ETH_HASH_FUNCTION_TOEPLITZ)
+#define BNXT_IS_HASH_FUNC_SIMPLE_XOR(b, f)	\
+	((b)->vnic_cap_flags & BNXT_VNIC_CAP_XOR_MODE && \
+	 ((f) != RTE_ETH_HASH_FUNCTION_SIMPLE_XOR))
 
 struct bnxt_vnic_info {
 	STAILQ_ENTRY(bnxt_vnic_info)	next;
@@ -73,6 +78,7 @@  struct bnxt_vnic_info {
 
 	STAILQ_HEAD(, bnxt_filter_info)	filter;
 	STAILQ_HEAD(, rte_flow)	flow_list;
+	uint8_t		ring_select_mode;
 };
 
 struct bnxt_vnic_queue_db {
@@ -83,6 +89,7 @@  struct bnxt_vnic_queue_db {
 
 /* RSS structure to pass values as an structure argument*/
 struct bnxt_vnic_rss_info {
+	uint32_t rss_func;
 	uint32_t rss_level;
 	uint64_t rss_types;
 	uint32_t key_len; /**< Hash key length in bytes. */
@@ -102,7 +109,7 @@  void bnxt_free_vnic_mem(struct bnxt *bp);
 int bnxt_alloc_vnic_mem(struct bnxt *bp);
 int bnxt_vnic_grp_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic);
 void bnxt_prandom_bytes(void *dest_ptr, size_t len);
-uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type);
+uint32_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type);
 int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp, uint64_t hash_f, uint32_t lvl);
 uint64_t bnxt_hwrm_to_rte_rss_level(struct bnxt *bp, uint32_t mode);
 
@@ -139,5 +146,12 @@  struct bnxt_vnic_info *
 bnxt_vnic_queue_id_get_next(struct bnxt *bp, uint16_t queue_id,
 			    uint16_t *vnic_idx);
 void bnxt_vnic_tpa_cfg(struct bnxt *bp, uint16_t queue_id, bool flag);
-
+uint8_t _bnxt_rte_to_hwrm_ring_select_mode(enum rte_eth_hash_function hash_f);
+int bnxt_rte_flow_to_hwrm_ring_select_mode(enum rte_eth_hash_function hash_f,
+					   uint64_t types, struct bnxt *bp,
+					   struct bnxt_vnic_info *vnic);
+int bnxt_rte_eth_to_hwrm_ring_select_mode(struct bnxt *bp, uint64_t types,
+					  struct bnxt_vnic_info *vnic);
+void bnxt_hwrm_rss_to_rte_hash_conf(struct bnxt_vnic_info *vnic,
+				    uint64_t *rss_conf);
 #endif