[3/3] net/bnxt: add support to set RSS hash level
diff mbox series

Message ID 20191207005919.10962-4-ajit.khaparde@broadcom.com
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers show
Series
  • add support for RSS level
Related show

Checks

Context Check Description
ci/travis-robot success Travis build: passed
ci/Intel-compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Ajit Khaparde Dec. 7, 2019, 12:59 a.m. UTC
This patch adds support to configure RSS hash level in the hardware,
if the firmware advertises such a capability.

Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 drivers/net/bnxt/bnxt.h        |  1 +
 drivers/net/bnxt/bnxt_ethdev.c |  7 ++++
 drivers/net/bnxt/bnxt_hwrm.c   |  9 +++-
 drivers/net/bnxt/bnxt_rxq.c    |  3 ++
 drivers/net/bnxt/bnxt_vnic.c   | 75 ++++++++++++++++++++++++++++++++++
 drivers/net/bnxt/bnxt_vnic.h   |  4 ++
 6 files changed, 97 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index e259c8239..d796ac539 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -536,6 +536,7 @@  struct bnxt {
 
 	uint32_t		vnic_cap_flags;
 #define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
+#define BNXT_VNIC_CAP_OUTER_RSS		BIT(1)
 	unsigned int		rx_nr_rings;
 	unsigned int		rx_cp_nr_rings;
 	unsigned int		rx_num_qs_per_vnic;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c70b072bf..a12aecc26 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -524,6 +524,8 @@  static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
 	dev_info->rx_offload_capa = BNXT_DEV_RX_OFFLOAD_SUPPORT;
 	if (bp->flags & BNXT_FLAG_PTP_SUPPORTED)
 		dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TIMESTAMP;
+	if (bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS)
+		dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_RSS_LEVEL;
 	dev_info->tx_offload_capa = BNXT_DEV_TX_OFFLOAD_SUPPORT;
 	dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
 
@@ -1404,6 +1406,8 @@  static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
 	/* Update the default RSS VNIC(s) */
 	vnic = BNXT_GET_DEFAULT_VNIC(bp);
 	vnic->hash_type = bnxt_rte_to_hwrm_hash_types(rss_conf->rss_hf);
+	vnic->hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss_conf->rss_level,
+						      rss_conf->rss_hf);
 
 	/*
 	 * If hashkey is not specified, use the previously configured
@@ -1438,6 +1442,9 @@  static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
 
 	/* RSS configuration is the same for all VNICs */
 	if (vnic && vnic->rss_hash_key) {
+		rss_conf->rss_level =
+			bnxt_hwrm_to_rte_rss_level(bp, vnic->hash_mode);
+
 		if (rss_conf->rss_key) {
 			len = rss_conf->rss_key_len <= HW_HASH_KEY_SIZE ?
 			      rss_conf->rss_key_len : HW_HASH_KEY_SIZE;
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index b1f908ee4..aba1ef34b 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -704,6 +704,7 @@  int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
 {
 	int rc = 0;
+	uint32_t flags;
 	struct hwrm_vnic_qcaps_input req = {.req_type = 0 };
 	struct hwrm_vnic_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
 
@@ -715,12 +716,16 @@  int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
 
 	HWRM_CHECK_RESULT();
 
-	if (rte_le_to_cpu_32(resp->flags) &
-	    HWRM_VNIC_QCAPS_OUTPUT_FLAGS_COS_ASSIGNMENT_CAP) {
+	flags = rte_le_to_cpu_32(resp->flags);
+
+	if (flags & HWRM_VNIC_QCAPS_OUTPUT_FLAGS_COS_ASSIGNMENT_CAP) {
 		bp->vnic_cap_flags |= BNXT_VNIC_CAP_COS_CLASSIFY;
 		PMD_DRV_LOG(INFO, "CoS assignment capability enabled\n");
 	}
 
+	if (flags & HWRM_VNIC_QCAPS_OUTPUT_FLAGS_OUTERMOST_RSS_CAP)
+		bp->vnic_cap_flags |= BNXT_VNIC_CAP_OUTER_RSS;
+
 	bp->max_tpa_v2 = rte_le_to_cpu_16(resp->max_aggs_supported);
 
 	HWRM_UNLOCK();
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index 457ebede0..fabc4663c 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -177,6 +177,9 @@  int bnxt_mq_rx_configure(struct bnxt *bp)
 			vnic = &bp->vnic_info[i];
 			vnic->hash_type =
 				bnxt_rte_to_hwrm_hash_types(rss->rss_hf);
+			vnic->hash_mode =
+				bnxt_rte_to_hwrm_hash_level(bp, rss->rss_level,
+							    rss->rss_hf);
 
 			/*
 			 * Use the supplied key if the key length is
diff --git a/drivers/net/bnxt/bnxt_vnic.c b/drivers/net/bnxt/bnxt_vnic.c
index 104342e13..8aebb6069 100644
--- a/drivers/net/bnxt/bnxt_vnic.c
+++ b/drivers/net/bnxt/bnxt_vnic.c
@@ -261,3 +261,78 @@  uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
 
 	return hwrm_type;
 }
+
+int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp,
+				uint32_t rss_level,
+				uint64_t hash_f)
+{
+	int mode = HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
+	bool l3 = !!(hash_f & (ETH_RSS_IPV4 | ETH_RSS_IPV6));
+	bool l4 = !!(hash_f & (ETH_RSS_NONFRAG_IPV4_UDP |
+			       ETH_RSS_NONFRAG_IPV6_UDP |
+			       ETH_RSS_NONFRAG_IPV4_TCP |
+			       ETH_RSS_NONFRAG_IPV6_TCP));
+	bool l3_only = l3 && !l4;
+	bool l3_and_l4 = l3 && l4;
+
+	/* If FW has not advertised capability to configure outer/inner
+	 * RSS hashing , just log a message. HW will work in default RSS mode.
+	 */
+	if (!(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS)) {
+		PMD_DRV_LOG(ERR, "RSS hash level cannot be configured\n");
+		return mode;
+	}
+
+	switch (rss_level) {
+	case 0:
+		mode = HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
+		break;
+	case 1:
+		if (l3_only)
+			mode =
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_2;
+		else if (l3_and_l4)
+			mode =
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_4;
+		break;
+	case 2:
+		if (l3_only)
+			mode =
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_2;
+		else if (l3_and_l4)
+			mode =
+			HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_4;
+		break;
+	default:
+		PMD_DRV_LOG(ERR,
+			    "No support for RSS hash level %d. Using default\n",
+			    rss_level);
+		break;
+	}
+
+	return mode;
+}
+
+int bnxt_hwrm_to_rte_rss_level(struct bnxt *bp, uint32_t hash_mode)
+{
+	int rss_level;
+
+	if (hash_mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_2 ||
+	    hash_mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_4)
+		rss_level = 1;
+	else if (hash_mode ==
+		 HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_2 ||
+		 hash_mode ==
+		 HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_4)
+		rss_level = 2;
+	else
+		rss_level = 0;
+
+	/* If FW has not advertised capability to configure inner/outer RSS
+	 * return default hash mode.
+	 */
+	if (!(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS))
+		rss_level = 0;
+
+	return rss_level;
+}
diff --git a/drivers/net/bnxt/bnxt_vnic.h b/drivers/net/bnxt/bnxt_vnic.h
index a372b899b..48445b026 100644
--- a/drivers/net/bnxt/bnxt_vnic.h
+++ b/drivers/net/bnxt/bnxt_vnic.h
@@ -69,4 +69,8 @@  int bnxt_alloc_vnic_mem(struct bnxt *bp);
 int bnxt_vnic_grp_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic);
 void prandom_bytes(void *dest_ptr, size_t len);
 uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type);
+int bnxt_hwrm_to_rte_rss_level(struct bnxt *bp, uint32_t hash_mode);
+int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp,
+				uint32_t rss_level,
+				uint64_t hash_f);
 #endif