Skip to content

Commit 467739b

Browse files
Michael Chankuba-moo
authored andcommitted
bnxt_en: Fix possible crash after creating sw mqprio TCs
The driver relies on netdev_get_num_tc() to get the number of HW offloaded mqprio TCs to allocate and free TX rings. This won't work and can potentially crash the system if software mqprio or taprio TCs have been setup. netdev_get_num_tc() will return the number of software TCs and it may cause the driver to allocate or free more TX rings that it should. Fix it by adding a bp->num_tc field to store the number of HW offload mqprio TCs for the device. Use bp->num_tc instead of netdev_get_num_tc(). This fixes a crash like this: BUG: kernel NULL pointer dereference, address: 0000000000000000 PGD 42b8404067 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 120 PID: 8661 Comm: ifconfig Kdump: loaded Tainted: G OE 5.18.16 #1 Hardware name: Lenovo ThinkSystem SR650 V3/SB27A92818, BIOS ESE114N-2.12 04/25/2023 RIP: 0010:bnxt_hwrm_cp_ring_alloc_p5+0x10/0x90 [bnxt_en] Code: 41 5c 41 5d 41 5e c3 cc cc cc cc 41 8b 44 24 08 66 89 03 eb c6 e8 b0 f1 7d db 0f 1f 44 00 00 41 56 41 55 41 54 55 48 89 fd 53 <48> 8b 06 48 89 f3 48 81 c6 28 01 00 00 0f b6 96 13 ff ff ff 44 8b RSP: 0018:ff65907660d1fa88 EFLAGS: 00010202 RAX: 0000000000000010 RBX: ff4dde1d907e4980 RCX: f400000000000000 RDX: 0000000000000010 RSI: 0000000000000000 RDI: ff4dde1d907e4980 RBP: ff4dde1d907e4980 R08: 000000000000000f R09: 0000000000000000 R10: ff4dde5f02671800 R11: 0000000000000008 R12: 0000000088888889 R13: 0500000000000000 R14: 00f0000000000000 R15: ff4dde5f02671800 FS: 00007f4b126b5740(0000) GS:ff4dde9bff600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000416f9c6002 CR4: 0000000000771ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> bnxt_hwrm_ring_alloc+0x204/0x770 [bnxt_en] bnxt_init_chip+0x4d/0x680 [bnxt_en] ? bnxt_poll+0x1a0/0x1a0 [bnxt_en] __bnxt_open_nic+0xd2/0x740 [bnxt_en] bnxt_open+0x10b/0x220 [bnxt_en] ? raw_notifier_call_chain+0x41/0x60 __dev_open+0xf3/0x1b0 __dev_change_flags+0x1db/0x250 dev_change_flags+0x21/0x60 devinet_ioctl+0x590/0x720 ? avc_has_extended_perms+0x1b7/0x420 ? _copy_from_user+0x3a/0x60 inet_ioctl+0x189/0x1c0 ? wp_page_copy+0x45a/0x6e0 sock_do_ioctl+0x42/0xf0 ? ioctl_has_perm.constprop.0.isra.0+0xbd/0x120 sock_ioctl+0x1ce/0x2e0 __x64_sys_ioctl+0x87/0xc0 do_syscall_64+0x59/0x90 ? syscall_exit_work+0x103/0x130 ? syscall_exit_to_user_mode+0x12/0x30 ? do_syscall_64+0x69/0x90 ? exc_page_fault+0x62/0x150 Fixes: c0c050c ("bnxt_en: New Broadcom ethernet driver.") Reviewed-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com> Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Link: https://lore.kernel.org/r/20240117234515.226944-6-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent c20f482 commit 467739b

File tree

5 files changed

+17
-11
lines changed

5 files changed

+17
-11
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3817,7 +3817,7 @@ static int bnxt_alloc_cp_rings(struct bnxt *bp)
38173817
{
38183818
bool sh = !!(bp->flags & BNXT_FLAG_SHARED_RINGS);
38193819
int i, j, rc, ulp_base_vec, ulp_msix;
3820-
int tcs = netdev_get_num_tc(bp->dev);
3820+
int tcs = bp->num_tc;
38213821

38223822
if (!tcs)
38233823
tcs = 1;
@@ -9946,7 +9946,7 @@ static int __bnxt_num_tx_to_cp(struct bnxt *bp, int tx, int tx_sets, int tx_xdp)
99469946

99479947
int bnxt_num_tx_to_cp(struct bnxt *bp, int tx)
99489948
{
9949-
int tcs = netdev_get_num_tc(bp->dev);
9949+
int tcs = bp->num_tc;
99509950

99519951
if (!tcs)
99529952
tcs = 1;
@@ -9955,7 +9955,7 @@ int bnxt_num_tx_to_cp(struct bnxt *bp, int tx)
99559955

99569956
static int bnxt_num_cp_to_tx(struct bnxt *bp, int tx_cp)
99579957
{
9958-
int tcs = netdev_get_num_tc(bp->dev);
9958+
int tcs = bp->num_tc;
99599959

99609960
return (tx_cp - bp->tx_nr_rings_xdp) * tcs +
99619961
bp->tx_nr_rings_xdp;
@@ -9985,7 +9985,7 @@ static void bnxt_setup_msix(struct bnxt *bp)
99859985
struct net_device *dev = bp->dev;
99869986
int tcs, i;
99879987

9988-
tcs = netdev_get_num_tc(dev);
9988+
tcs = bp->num_tc;
99899989
if (tcs) {
99909990
int i, off, count;
99919991

@@ -10017,8 +10017,10 @@ static void bnxt_setup_inta(struct bnxt *bp)
1001710017
{
1001810018
const int len = sizeof(bp->irq_tbl[0].name);
1001910019

10020-
if (netdev_get_num_tc(bp->dev))
10020+
if (bp->num_tc) {
1002110021
netdev_reset_tc(bp->dev);
10022+
bp->num_tc = 0;
10023+
}
1002210024

1002310025
snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx",
1002410026
0);
@@ -10244,8 +10246,8 @@ static void bnxt_clear_int_mode(struct bnxt *bp)
1024410246

1024510247
int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
1024610248
{
10247-
int tcs = netdev_get_num_tc(bp->dev);
1024810249
bool irq_cleared = false;
10250+
int tcs = bp->num_tc;
1024910251
int rc;
1025010252

1025110253
if (!bnxt_need_reserve_rings(bp))
@@ -10271,6 +10273,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
1027110273
bp->tx_nr_rings - bp->tx_nr_rings_xdp)) {
1027210274
netdev_err(bp->dev, "tx ring reservation failure\n");
1027310275
netdev_reset_tc(bp->dev);
10276+
bp->num_tc = 0;
1027410277
if (bp->tx_nr_rings_xdp)
1027510278
bp->tx_nr_rings_per_tc = bp->tx_nr_rings_xdp;
1027610279
else
@@ -13800,7 +13803,7 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
1380013803
return -EINVAL;
1380113804
}
1380213805

13803-
if (netdev_get_num_tc(dev) == tc)
13806+
if (bp->num_tc == tc)
1380413807
return 0;
1380513808

1380613809
if (bp->flags & BNXT_FLAG_SHARED_RINGS)
@@ -13818,9 +13821,11 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
1381813821
if (tc) {
1381913822
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc;
1382013823
netdev_set_num_tc(dev, tc);
13824+
bp->num_tc = tc;
1382113825
} else {
1382213826
bp->tx_nr_rings = bp->tx_nr_rings_per_tc;
1382313827
netdev_reset_tc(dev);
13828+
bp->num_tc = 0;
1382413829
}
1382513830
bp->tx_nr_rings += bp->tx_nr_rings_xdp;
1382613831
tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings);

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,6 +2225,7 @@ struct bnxt {
22252225
u8 tc_to_qidx[BNXT_MAX_QUEUE];
22262226
u8 q_ids[BNXT_MAX_QUEUE];
22272227
u8 max_q;
2228+
u8 num_tc;
22282229

22292230
unsigned int current_interval;
22302231
#define BNXT_TIMER_INTERVAL HZ

drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask)
228228
}
229229
}
230230
if (bp->ieee_ets) {
231-
int tc = netdev_get_num_tc(bp->dev);
231+
int tc = bp->num_tc;
232232

233233
if (!tc)
234234
tc = 1;

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ static void bnxt_get_channels(struct net_device *dev,
884884
if (max_tx_sch_inputs)
885885
max_tx_rings = min_t(int, max_tx_rings, max_tx_sch_inputs);
886886

887-
tcs = netdev_get_num_tc(dev);
887+
tcs = bp->num_tc;
888888
tx_grps = max(tcs, 1);
889889
if (bp->tx_nr_rings_xdp)
890890
tx_grps++;
@@ -944,7 +944,7 @@ static int bnxt_set_channels(struct net_device *dev,
944944
if (channel->combined_count)
945945
sh = true;
946946

947-
tcs = netdev_get_num_tc(dev);
947+
tcs = bp->num_tc;
948948

949949
req_tx_rings = sh ? channel->combined_count : channel->tx_count;
950950
req_rx_rings = sh ? channel->combined_count : channel->rx_count;

drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
407407
if (prog)
408408
tx_xdp = bp->rx_nr_rings;
409409

410-
tc = netdev_get_num_tc(dev);
410+
tc = bp->num_tc;
411411
if (!tc)
412412
tc = 1;
413413
rc = bnxt_check_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings,

0 commit comments

Comments
 (0)