[3/3] net/bnxt: add support to set RSS hash level
Checks
Commit Message
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(-)
@@ -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;
@@ -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;
@@ -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();
@@ -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
@@ -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;
+}
@@ -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