From: Mohammad Shuab Siddique <[email protected]>

In bnxt_hwrm_vnic_rss_cfg_hash_mode_p5(), the VF path unconditionally
accessed vnic->fw_grp_ids[0], but fw_grp_ids is NULL when no RSS
contexts have been allocated (num_lb_ctxts == 0). The
bnxt_hwrm_vnic_rss_cfg_p5() call just before it skips its loop when
num_lb_ctxts == 0, so the NULL pointer passed through silently to
this function and caused a segfault on the next RSS hash-level
change after port stop.

A separate HWRM_VNIC_RSS_CFG call to set hash_mode on its own, with
ring_grp_tbl_addr=0 and hash_type=0, is also unsafe on P5/P7 VFs:
firmware treats those zeroes literally and wipes the ring table, so
all traffic lands on queue 0 regardless of the configured RSS level.

Set hash_mode_flags directly in bnxt_hwrm_vnic_rss_cfg_p5() for VFs
on P5/P7, translating DEFAULT to INNERMOST. Firmware now receives one
complete call per context with the ring table, hash type, and hash
mode all set together.

Embedding hash_mode_flags there alone would permanently short-circuit
the separate hash-mode call in bnxt_hwrm_vnic_rss_cfg_hash_mode_p5()
for every VF, silently dropping a trusted VF's explicit RSS
hash-level request (e.g. "rss level-outer") no matter what value was
requested. Firmware's own gate for that separate call (vnic_id ==
0xFFFF && rss_ctx_idx == 0xFFFF) explicitly permits trusted VFs, not
just PFs, to use it. So instead of skipping VFs unconditionally,
bnxt_hwrm_vnic_rss_cfg_hash_mode_p5() now only short-circuits for a
VF that is untrusted or has no initialized RSS context (fw_grp_ids/
num_lb_ctxts), and lets a trusted VF with an initialized context
reach the same call PFs already use. The per-context ring-table-wipe
fix above is unchanged either way.

Fixes: 3fd58de5a903 ("net/bnxt: fix RSS hash mode configuration for VF")
Cc: [email protected]

Signed-off-by: Farah Smith <[email protected]>
Signed-off-by: Mohammad Shuab Siddique <[email protected]>
---
 drivers/net/bnxt/bnxt_hwrm.c | 79 +++++++++++++-----------------------
 1 file changed, 28 insertions(+), 51 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 1615b36aae..84e2aee863 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -2893,15 +2893,16 @@ bnxt_hwrm_vnic_rss_cfg_p5(struct bnxt *bp, struct 
bnxt_vnic_info *vnic)
 
                req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
                req.hash_type = rte_cpu_to_le_32(bnxt_sanitize_rss_type(bp, 
vnic->hash_type));
-               /* Update req with vnic ring_select_mode for P7 */
                if (BNXT_CHIP_P7(bp))
                        req.ring_select_mode = vnic->ring_select_mode;
-               /* When the vnic_id in the request field is a valid
-                * one, the hash_mode_flags in the request field must
-                * be set to DEFAULT. And any request to change the
-                * default behavior must be done in a separate call
-                * to HWRM_VNIC_RSS_CFG by exclusively setting hash
-                * mode and vnic_id, rss_ctx_idx to INVALID.
+
+               /* Do not embed hash_mode_flags here for VFs. Doing so, plus
+                * syncing prev_hash_mode below, permanently short-circuits
+                * bnxt_hwrm_vnic_rss_cfg_hash_mode_p5()'s guard for every VF,
+                * so a trusted VF's explicit RSS hash-level request (e.g.
+                * rss level-outer) is silently dropped. Firmware's own gate
+                * (vnic_rss_cfg_cmd()) permits trusted VFs on that call, so
+                * treat VFs the same as PFs here.
                 */
                req.hash_mode_flags = BNXT_HASH_MODE_DEFAULT;
 
@@ -2930,70 +2931,46 @@ static int
 bnxt_hwrm_vnic_rss_cfg_hash_mode_p5(struct bnxt *bp, struct bnxt_vnic_info 
*vnic)
 {
        struct hwrm_vnic_rss_cfg_output *resp = bp->hwrm_cmd_resp_addr;
-       struct hwrm_vnic_rss_cfg_input req = {.req_type = 0 };
+       struct hwrm_vnic_rss_cfg_input req = {.req_type = 0};
        int rc = 0;
 
-       /* The reason we are returning success here is that this
-        * call is in the context of user/stack RSS configuration.
-        * Even though OUTER RSS is not supported, the normal RSS
-        * configuration should continue to work.
-        */
+       /* Return success when outer RSS is unsupported so normal RSS works. */
        if ((BNXT_CHIP_P5(bp) && BNXT_VNIC_OUTER_RSS_UNSUPPORTED(bp)) ||
            (!BNXT_CHIP_P5(bp) && !(bp->vnic_cap_flags & 
BNXT_VNIC_CAP_OUTER_RSS)))
                return 0;
 
-       /* TODO Revisit for Thor 2 */
-       /* if (BNXT_CHIP_P5_P7(bp))
-        *      bnxt_hwrm_vnic_rss_cfg_p5(bp, vnic);
-        */
-       /* Don't call RSS hash level configuration if the current
-        * hash level is the same as the hash level that is requested.
-        */
        if (vnic->prev_hash_mode == vnic->hash_mode)
                return 0;
 
+       /* Trusted VFs now reach this call the same as PFs; firmware's own
+        * gate (IS_PF_FID() || pcie_func_is_trusted_vf()) restricts which
+        * callers it accepts the request from. Firmware would reject a
+        * request from an untrusted VF, so keep it a silent no-op here
+        * instead of surfacing a new HWRM error.
+        * The fw_grp_ids/num_lb_ctxts check guards against a NULL RSS
+        * context that is not yet initialized or has been torn down by
+        * a port stop.
+        */
+       if (BNXT_VF(bp) &&
+           (!BNXT_VF_IS_TRUSTED(bp) || !vnic->fw_grp_ids || 
!vnic->num_lb_ctxts))
+               return 0;
+
        HWRM_PREP(&req, HWRM_VNIC_RSS_CFG, BNXT_USE_CHIMP_MB);
 
-       /* For FW, hash_mode == DEFAULT means that
-        * the FW is capable of doing INNER & OUTER RSS as well.
-        * DEFAULT doesn't mean that the FW is
-        * going to change the hash_mode to INNER. However, for
-        * the USER, DEFAULT means, change the hash mode to the
-        * NIC's DEFAULT hash mode which is INNER.
-        *
-        * Hence, driver should make the translation of hash_mode
-        * to INNERMOST when hash_mode from the dpdk stack is
-        * DEFAULT.
+       /* FW DEFAULT keeps existing hash level; translate to INNERMOST so
+        * the NIC uses its hardware default (inner headers).
         */
        if (vnic->hash_mode == BNXT_HASH_MODE_DEFAULT)
                req.hash_mode_flags = BNXT_HASH_MODE_INNERMOST;
        else
                req.hash_mode_flags = vnic->hash_mode;
 
-       /* VFs must use actual vnic_id for per-VNIC configuration.
-        * PFs can use INVALID vnic_id for global configuration.
-        * This is because VFs don't have permission to configure
-        * global hash mode, even if they're trusted.
-        */
-       if (BNXT_VF(bp)) {
-               req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
-               req.rss_ctx_idx = rte_cpu_to_le_16(vnic->fw_grp_ids[0]);
-               PMD_DRV_LOG_LINE(DEBUG, "VF using per-VNIC RSS config 
(vnic_id=%u)",
-                               vnic->fw_vnic_id);
-       } else {
-               req.vnic_id = rte_cpu_to_le_16(BNXT_DFLT_VNIC_ID_INVALID);
-               req.rss_ctx_idx = rte_cpu_to_le_16(BNXT_RSS_CTX_IDX_INVALID);
-               PMD_DRV_LOG_LINE(DEBUG, "PF using global RSS config");
-       }
-
+       req.vnic_id = rte_cpu_to_le_16(BNXT_DFLT_VNIC_ID_INVALID);
+       req.rss_ctx_idx = rte_cpu_to_le_16(BNXT_RSS_CTX_IDX_INVALID);
        PMD_DRV_LOG_LINE(DEBUG, "RSS CFG: Hash level %d", req.hash_mode_flags);
-       rc = bnxt_hwrm_send_message(bp, &req, sizeof(req),
-                                   BNXT_USE_CHIMP_MB);
+       rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
 
        HWRM_CHECK_RESULT();
-       /* Store the programmed hash_mode in prev_hash_mode so that
-        * it can checked against the next user requested hash mode.
-        */
        if (!rc)
                vnic->prev_hash_mode = vnic->hash_mode;
        HWRM_UNLOCK();
-- 
2.47.3

Reply via email to