Merge branch 'fix-a-variety-of-tpa-bugs'

Joe Damato says:

====================
Fix a variety of TPA bugs

I am sending this series as an extension to my v4 [1] which was just 1 patch.

Note that patch 5 of this series can now cause the device to fail closed if
memory is tight; bnxt_init_nic propagates an error that was previously
swallowed and fails closed instead of succeeding in a degraded state. If the
maintainers want the device to come up with a partially populated rx_tpa[],
then patch 5 can be dropped and this series can still be applied
and will otherwise work as intended.

This series addresses a variety of bugs orbiting the TPA code in the bnxt
driver that Sashiko (or Clashiko or whatever) pointed out and the series ends
with the patch from the v4 [1].

A lot of the noise generated by the AIs while reviewing my v4 are unrelated
bugs with different fixes tags that, IMHO, distract a bit from the crash at
boot that is currently occurring with Thor2 hardware on recent kernels.

That said, I've tried to wrangle this series together which I hope will solve
most of the important bugs the AIs are feeling something about.

I do not know what other rabbit holes the AIs will find when I submit this
series, but if there is some reasonable stop-gap that we can get applied to
fix the crashes on Thor2 (while I iterate on the rest of the bugs at the
pleasure of the AIs) that would be excellent.

I boot tested this on a Thor1 and a Thor2 machine and there were no crashes at
boot.

[1]: https://lore.kernel.org/all/20260828190900.1767611-1-joe@dama.to/
====================

Link: https://patch.msgid.link/20260902015652.2421609-1-joe@dama.to
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2026-09-08 10:47:06 +02:00
commit ae20d47d26
2 changed files with 43 additions and 16 deletions

View File

@ -1534,14 +1534,16 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
return 0;
}
static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
static u16 bnxt_alloc_agg_idx(struct bnxt *bp, 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;
u16 idx = agg_id & (bp->max_tpa_roundup_size - 1);
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)
idx = find_first_zero_bit(map->agg_idx_bmap,
bp->max_tpa_roundup_size);
if (idx >= bp->max_tpa_roundup_size)
return INVALID_HW_RING_ID;
}
__set_bit(idx, map->agg_idx_bmap);
@ -1606,7 +1608,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
agg_id = TPA_START_AGG_ID_P5(tpa_start);
agg_id = bnxt_alloc_agg_idx(rxr, agg_id);
agg_id = bnxt_alloc_agg_idx(bp, 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,
@ -3604,7 +3606,7 @@ static void bnxt_free_one_tpa_info_data(struct bnxt *bp,
{
int i;
for (i = 0; i < bp->max_tpa; i++) {
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[i];
u8 *data = tpa_info->data;
@ -3801,7 +3803,7 @@ static void bnxt_free_one_tpa_info(struct bnxt *bp,
kfree(rxr->rx_tpa_idx_map);
rxr->rx_tpa_idx_map = NULL;
if (rxr->rx_tpa) {
for (i = 0; i < bp->max_tpa; i++) {
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
kfree(rxr->rx_tpa[i].agg_arr);
rxr->rx_tpa[i].agg_arr = NULL;
}
@ -3827,13 +3829,14 @@ static int bnxt_alloc_one_tpa_info(struct bnxt *bp,
struct rx_agg_cmp *agg;
int i;
rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info, bp->max_tpa);
rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info,
bp->max_tpa_roundup_size);
if (!rxr->rx_tpa)
return -ENOMEM;
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
return 0;
for (i = 0; i < bp->max_tpa; i++) {
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
agg = kzalloc_objs(*agg, MAX_SKB_FRAGS);
if (!agg)
return -ENOMEM;
@ -3852,6 +3855,9 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
bp->max_tpa = MAX_TPA;
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
/* TPA is not supported at all, so there is nothing to
* allocate.
*/
if (!bp->max_tpa_v2)
return 0;
bp->max_tpa = min_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
@ -3859,6 +3865,7 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
if (bp->max_tpa <= 32 && BNXT_CHIP_P5(bp) && !BNXT_NPAR(bp))
bp->max_tpa = MAX_TPA_P5;
}
bp->max_tpa_roundup_size = roundup_pow_of_two(bp->max_tpa);
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@ -4571,7 +4578,7 @@ static int bnxt_alloc_one_tpa_info_data(struct bnxt *bp,
u8 *data;
int i;
for (i = 0; i < bp->max_tpa; i++) {
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
GFP_KERNEL);
if (!data)
@ -5026,7 +5033,8 @@ void bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
bnxt_get_max_rings(bp, &rx, &tx, true);
if (rx > 1) {
bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
bp->dev->hw_features |= NETIF_F_LRO;
if (BNXT_SUPPORTS_TPA(bp))
bp->dev->hw_features |= NETIF_F_LRO;
}
}
@ -11362,8 +11370,13 @@ static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init)
static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init)
{
int rc;
bnxt_init_cp_rings(bp);
bnxt_init_rx_rings(bp);
rc = bnxt_init_rx_rings(bp);
if (rc)
return rc;
bnxt_init_tx_rings(bp);
bnxt_init_ring_grps(bp, irq_re_init);
bnxt_init_vnics(bp);
@ -14627,7 +14640,14 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
rxr->rx_sw_agg_prod = 0;
rxr->rx_next_cons = 0;
rxr->bnapi->in_reset = false;
bnxt_alloc_one_rx_ring(bp, i);
rc = bnxt_alloc_one_rx_ring(bp, i);
if (rc) {
netdev_warn(bp->dev, "RX ring reset failed to allocate buffers, rc = %d, falling back to global reset\n",
rc);
bnxt_reset_task(bp, true);
bnxt_rtnl_unlock_sp(bp);
return;
}
cpr = &rxr->bnapi->cp_ring;
cpr->sw_stats->rx.rx_resets++;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
@ -16356,6 +16376,8 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
clone->need_head_pool = false;
clone->rx_page_size = qcfg->rx_page_size;
clone->rx_agg_bmap = NULL;
clone->rx_tpa = NULL;
clone->rx_tpa_idx_map = NULL;
rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
if (rc)
@ -16399,11 +16421,16 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
bnxt_alloc_one_rx_ring_skb(bp, clone, idx);
if (bp->flags & BNXT_FLAG_AGG_RINGS)
bnxt_alloc_one_rx_ring_netmem(bp, clone, idx);
if (bp->flags & BNXT_FLAG_TPA)
bnxt_alloc_one_tpa_info_data(bp, clone);
if (bp->flags & BNXT_FLAG_TPA) {
rc = bnxt_alloc_one_tpa_info_data(bp, clone);
if (rc)
goto err_free_rx_ring_skbs;
}
return 0;
err_free_rx_ring_skbs:
bnxt_free_one_rx_ring_skbs(bp, clone);
err_free_tpa_info:
bnxt_free_one_tpa_info(bp, clone);
err_free_rx_agg_ring:

View File

@ -789,7 +789,6 @@ struct nqe_cn {
#define MAX_TPA 64
#define MAX_TPA_P5 256
#define MAX_TPA_P5_MASK (MAX_TPA_P5 - 1)
#define MAX_TPA_SEGS_P5 0x3f
#if (BNXT_PAGE_SHIFT == 16)
@ -2381,6 +2380,7 @@ struct bnxt {
u16 max_tpa_v2;
u16 max_tpa;
u16 max_tpa_roundup_size;
u32 rx_buf_size;
u32 rx_buf_use_size; /* useable size */
u16 rx_offset;