Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bnxt_en: Fix potential data corruption with HW GRO/LRO

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>

authored by

Srijit Bose and committed by
Jakub Kicinski
ffeafa65 92e6e0a8

+13 -6
+12 -3
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 1482 1482 struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; 1483 1483 u16 idx = agg_id & MAX_TPA_P5_MASK; 1484 1484 1485 - if (test_bit(idx, map->agg_idx_bmap)) 1486 - idx = find_first_zero_bit(map->agg_idx_bmap, 1487 - BNXT_AGG_IDX_BMAP_SIZE); 1485 + if (test_bit(idx, map->agg_idx_bmap)) { 1486 + idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5); 1487 + if (idx >= MAX_TPA_P5) 1488 + return INVALID_HW_RING_ID; 1489 + } 1488 1490 __set_bit(idx, map->agg_idx_bmap); 1489 1491 map->agg_id_tbl[agg_id] = idx; 1490 1492 return idx; ··· 1550 1548 if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { 1551 1549 agg_id = TPA_START_AGG_ID_P5(tpa_start); 1552 1550 agg_id = bnxt_alloc_agg_idx(rxr, agg_id); 1551 + if (unlikely(agg_id == INVALID_HW_RING_ID)) { 1552 + netdev_warn(bp->dev, "Unable to allocate agg ID for ring %d, agg 0x%x\n", 1553 + rxr->bnapi->index, 1554 + TPA_START_AGG_ID_P5(tpa_start)); 1555 + bnxt_sched_reset_rxr(bp, rxr); 1556 + return; 1557 + } 1553 1558 } else { 1554 1559 agg_id = TPA_START_AGG_ID(tpa_start); 1555 1560 }
+1 -3
drivers/net/ethernet/broadcom/bnxt/bnxt.h
··· 1080 1080 struct rx_agg_cmp *agg_arr; 1081 1081 }; 1082 1082 1083 - #define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG) 1084 - 1085 1083 struct bnxt_tpa_idx_map { 1086 1084 u16 agg_id_tbl[1024]; 1087 - unsigned long agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE]; 1085 + DECLARE_BITMAP(agg_idx_bmap, MAX_TPA_P5); 1088 1086 }; 1089 1087 1090 1088 struct bnxt_rx_ring_info {