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: fix bnxt_get_avail_msix() returning negative values

Current net-next/main does not boot for older chipsets e.g. Stratus.

Sample dmesg:
[ 11.368315] bnxt_en 0000:02:00.0 (unnamed net_device) (uninitialized): Able to reserve only 0 out of 9 requested RX rings
[ 11.390181] bnxt_en 0000:02:00.0 (unnamed net_device) (uninitialized): Unable to reserve tx rings
[ 11.438780] bnxt_en 0000:02:00.0 (unnamed net_device) (uninitialized): 2nd rings reservation failed.
[ 11.487559] bnxt_en 0000:02:00.0 (unnamed net_device) (uninitialized): Not enough rings available.
[ 11.506012] bnxt_en 0000:02:00.0: probe with driver bnxt_en failed with error -12

This is caused by bnxt_get_avail_msix() returning a negative value for
these chipsets not using the new resource manager i.e. !BNXT_NEW_RM.
This in turn causes hwr.cp in __bnxt_reserve_rings() to be set to 0.

In the current call stack, __bnxt_reserve_rings() is called from
bnxt_set_dflt_rings() before bnxt_init_int_mode(). Therefore,
bp->total_irqs is always 0 and for !BNXT_NEW_RM bnxt_get_avail_msix()
always returns a negative number.

Historically, MSIX vectors were requested by the RoCE driver during
run-time and bnxt_get_avail_msix() was used for this purpose. Today,
RoCE MSIX vectors are statically allocated. bnxt_get_avail_msix() should
only be called for the BNXT_NEW_RM() case to reserve the MSIX ahead of
time for RoCE use.

bnxt_get_avail_msix() is also be simplified to handle the BNXT_NEW_RM()
case only.

Fixes: d630624ebd70 ("bnxt_en: Utilize ulp client resources if RoCE is not registered")
Signed-off-by: David Wei <dw@davidwei.uk>
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Link: https://lore.kernel.org/r/20240502203757.3761827-1-dw@davidwei.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

David Wei and committed by
Jakub Kicinski
5bfadc57 c1742dcb

+5 -13
+5 -12
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 7469 7469 hwr->stat && (hwr->cp_p5 || !(bp->flags & BNXT_FLAG_CHIP_P5_PLUS)); 7470 7470 } 7471 7471 7472 + static int bnxt_get_avail_msix(struct bnxt *bp, int num); 7473 + 7472 7474 static int __bnxt_reserve_rings(struct bnxt *bp) 7473 7475 { 7474 7476 struct bnxt_hw_rings hwr = {0}; ··· 7483 7481 if (!bnxt_need_reserve_rings(bp)) 7484 7482 return 0; 7485 7483 7486 - if (!bnxt_ulp_registered(bp->edev)) { 7484 + if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(bp->edev)) { 7487 7485 ulp_msix = bnxt_get_avail_msix(bp, bp->ulp_num_msix_want); 7488 7486 if (!ulp_msix) 7489 7487 bnxt_set_ulp_stat_ctxs(bp, 0); ··· 10486 10484 return bnxt_get_max_func_stat_ctxs(bp) - bnxt_get_func_stat_ctxs(bp); 10487 10485 } 10488 10486 10489 - int bnxt_get_avail_msix(struct bnxt *bp, int num) 10487 + static int bnxt_get_avail_msix(struct bnxt *bp, int num) 10490 10488 { 10491 - int max_cp = bnxt_get_max_func_cp_rings(bp); 10492 10489 int max_irq = bnxt_get_max_func_irqs(bp); 10493 10490 int total_req = bp->cp_nr_rings + num; 10494 - int max_idx, avail_msix; 10495 - 10496 - max_idx = bp->total_irqs; 10497 - if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS)) 10498 - max_idx = min_t(int, bp->total_irqs, max_cp); 10499 - avail_msix = max_idx - bp->cp_nr_rings; 10500 - if (!BNXT_NEW_RM(bp) || avail_msix >= num) 10501 - return avail_msix; 10502 10491 10503 10492 if (max_irq < total_req) { 10504 10493 num = max_irq - bp->cp_nr_rings; ··· 10622 10629 if (!bnxt_need_reserve_rings(bp)) 10623 10630 return 0; 10624 10631 10625 - if (!bnxt_ulp_registered(bp->edev)) { 10632 + if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(bp->edev)) { 10626 10633 int ulp_msix = bnxt_get_avail_msix(bp, bp->ulp_num_msix_want); 10627 10634 10628 10635 if (ulp_msix > bp->ulp_num_msix_want)
-1
drivers/net/ethernet/broadcom/bnxt/bnxt.h
··· 2738 2738 unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp); 2739 2739 unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp); 2740 2740 unsigned int bnxt_get_avail_cp_rings_for_en(struct bnxt *bp); 2741 - int bnxt_get_avail_msix(struct bnxt *bp, int num); 2742 2741 int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init); 2743 2742 void bnxt_tx_disable(struct bnxt *bp); 2744 2743 void bnxt_tx_enable(struct bnxt *bp);