]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bnxt_en: Fix potential data corruption with HW GRO/LRO
authorSrijit Bose <srijit.bose@broadcom.com>
Wed, 31 Dec 2025 08:36:25 +0000 (00:36 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jan 2026 12:12:11 +0000 (13:12 +0100)
[ Upstream commit ffeafa65b2b26df2f5b5a6118d3174f17bd12ec5 ]

Fix the max number of bits passed to find_first_zero_bit() in
bnxt_alloc_agg_idx().  We were incorrectly passing the number of
long words.  find_first_zero_bit() may fail to find a zero bit and
cause a wrong ID to be used.  If the wrong ID is already in use, this
can cause data corruption.  Sometimes an error like this can also be
seen:

bnxt_en 0000:83:00.0 enp131s0np0: TPA end agg_buf 2 != expected agg_bufs 1

Fix it by passing the correct number of bits MAX_TPA_P5.  Use
DECLARE_BITMAP() to more cleanly define the bitmap.  Add a sanity
check to warn if a bit cannot be found and reset the ring [MChan].

Fixes: ec4d8e7cf024 ("bnxt_en: Add TPA ID mapping logic for 57500 chips.")
Reviewed-by: Ray Jui <ray.jui@broadcom.com>
Signed-off-by: Srijit Bose <srijit.bose@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20251231083625.3911652-1-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index 7fa215b320603661fcb99ecf2f721fc02019aa95..fd54a194a5e5fe92b76b961b34c03caeef43b33b 100644 (file)
@@ -1218,9 +1218,11 @@ static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
        struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map;
        u16 idx = agg_id & MAX_TPA_P5_MASK;
 
-       if (test_bit(idx, map->agg_idx_bmap))
-               idx = find_first_zero_bit(map->agg_idx_bmap,
-                                         BNXT_AGG_IDX_BMAP_SIZE);
+       if (test_bit(idx, map->agg_idx_bmap)) {
+               idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5);
+               if (idx >= MAX_TPA_P5)
+                       return INVALID_HW_RING_ID;
+       }
        __set_bit(idx, map->agg_idx_bmap);
        map->agg_id_tbl[agg_id] = idx;
        return idx;
@@ -1253,6 +1255,13 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        if (bp->flags & BNXT_FLAG_CHIP_P5) {
                agg_id = TPA_START_AGG_ID_P5(tpa_start);
                agg_id = bnxt_alloc_agg_idx(rxr, agg_id);
+               if (unlikely(agg_id == INVALID_HW_RING_ID)) {
+                       netdev_warn(bp->dev, "Unable to allocate agg ID for ring %d, agg 0x%x\n",
+                                   rxr->bnapi->index,
+                                   TPA_START_AGG_ID_P5(tpa_start));
+                       bnxt_sched_reset_rxr(bp, rxr);
+                       return;
+               }
        } else {
                agg_id = TPA_START_AGG_ID(tpa_start);
        }
index b7b07beb17ffbdd82f39ffd91cf41efb917c738e..c2122d5cda62291bec29d4d3d339dd1bc84aaafa 100644 (file)
@@ -870,11 +870,9 @@ struct bnxt_tpa_info {
        struct rx_agg_cmp       *agg_arr;
 };
 
-#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG)
-
 struct bnxt_tpa_idx_map {
        u16             agg_id_tbl[1024];
-       unsigned long   agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE];
+       DECLARE_BITMAP(agg_idx_bmap, MAX_TPA_P5);
 };
 
 struct bnxt_rx_ring_info {