]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bnxt_en: Determine and store default RX ring in vnic structure
authorShravya KN <shravya.k-n@broadcom.com>
Fri, 31 Jul 2026 19:09:34 +0000 (12:09 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 5 Aug 2026 02:54:33 +0000 (19:54 -0700)
Each VNIC has a default RX ring.  The purpose of the default RX ring
is to provide a destination for any packets that cannot be parsed by
the RSS logic.  Up until now, the default RX ring is always Ring 0.

We neglected to take care of this default RX ring when adding the
queue restart feature.  If ring 0 (default ring) is re-started, it
may now have a new FW ring ID after freeing the old one and
allocating a new one.  The VNIC now may have a stale default ring
and it may generate an internal exception.  This exception may
appear in dmesg:

FW reported unknown error type 10

The best way to resolve this issue is to use a more appropriate
ring for the default ring instead of always ring 0.  Ring 0 may not
even be in the RSS table, especially on a new RSS context.

This patch adds the logic to determine and store the proper default
RX ring for a VNIC.  For an RSS VNIC, the default ring is the lowest
ring number in the RSS table.  The next patch will add proper logic
to update the VNIC if the default ring changes after queue restart.

Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20260731190937.807270-3-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index 4599b6e0d219467283c72c788911bfd79c625932..8b1f4e9fc7803c32c4d8180514d478ede9f23823 100644 (file)
@@ -6704,25 +6704,36 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
 static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 {
        bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
-       u16 i, j;
+       u16 i, j, min_j = bp->rx_nr_rings - 1;
 
        if (!vnic->rss_table)
-               return;
+               goto skip_rss_tbl;
 
        /* Fill the RSS indirection table with ring group ids */
        for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
                if (!no_rss)
                        j = bp->rss_indir_tbl[i];
+               min_j = min(j, min_j);
                vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]);
        }
+
+skip_rss_tbl:
+       if (vnic->rss_table && !no_rss)
+               vnic->default_rx_ring = min_j;
+       else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
+               vnic->default_rx_ring = vnic->vnic_id - 1;
+       else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
+               vnic->default_rx_ring = bp->rx_nr_rings - 1;
+       else
+               vnic->default_rx_ring = 0;
 }
 
 static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
                                    struct bnxt_vnic_info *vnic)
 {
+       u16 tbl_size, i, min_j = bp->rx_nr_rings - 1;
        __le16 *ring_tbl = vnic->rss_table;
        struct bnxt_rx_ring_info *rxr;
-       u16 tbl_size, i;
 
        tbl_size = bnxt_get_rxfh_indir_size(bp->dev);
 
@@ -6735,6 +6746,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
                        j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i];
                else
                        j = bp->rss_indir_tbl[i];
+               min_j = min(j, min_j);
                rxr = &bp->rx_ring[j];
 
                ring_id = rxr->rx_ring_struct.fw_ring_id;
@@ -6742,6 +6754,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
                ring_id = bnxt_cp_ring_for_rx(bp, rxr);
                *ring_tbl++ = cpu_to_le16(ring_id);
        }
+       vnic->default_rx_ring = min_j;
 }
 
 static void
@@ -6938,8 +6951,9 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
                return rc;
 
        if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
-               struct bnxt_rx_ring_info *rxr = &bp->rx_ring[0];
+               struct bnxt_rx_ring_info *rxr;
 
+               rxr = &bp->rx_ring[vnic->default_rx_ring];
                req->default_rx_ring_id =
                        cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
                req->default_cmpl_ring_id =
@@ -6972,13 +6986,7 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
                req->cos_rule = cpu_to_le16(0xffff);
        }
 
-       if (vnic->flags & BNXT_VNIC_RSS_FLAG)
-               ring = 0;
-       else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
-               ring = vnic->vnic_id - 1;
-       else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp))
-               ring = bp->rx_nr_rings - 1;
-
+       ring = vnic->default_rx_ring;
        grp_idx = bp->rx_ring[ring].bnapi->index;
        req->dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);
        req->lb_rule = cpu_to_le16(0xffff);
@@ -11171,6 +11179,9 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp)
                return rc;
        }
 
+       /* Setup the proper default RX ring */
+       bnxt_fill_hw_rss_tbl(bp, vnic);
+
        rc = bnxt_hwrm_vnic_cfg(bp, vnic);
        if (rc) {
                netdev_err(bp->dev, "Cannot allocate special vnic for NS2 A0: %x\n",
index 6335dfc14c985ba11cd5dd7cf6ce415e1aeb9dd1..44ea8fc7b766d7e48332b9743b3c75af78ed942e 100644 (file)
@@ -1334,6 +1334,7 @@ struct bnxt_vnic_info {
 #define BNXT_VNIC_RSSCTX_FLAG          0x40
        struct ethtool_rxfh_context *rss_ctx;
        u32             vnic_id;
+       u16             default_rx_ring;
 };
 
 struct bnxt_rss_ctx {