Skip to content

Commit 1e0079e

Browse files
Jinjian-SongNipaLocal
authored and
NipaLocal
committed
net: wwan: t7xx: Fix napi rx poll issue
When driver handles the napi rx polling requests, the netdev might have been released by the dellink logic triggered by the disconnect operation on user plane. However, in the logic of processing skb in polling, an invalid netdev is still being used, which causes a panic. BUG: kernel NULL pointer dereference, address: 00000000000000f1 Oops: 0000 [kernel-patches#1] PREEMPT SMP NOPTI RIP: 0010:dev_gro_receive+0x3a/0x620 [...] Call Trace: <IRQ> ? __die_body+0x68/0xb0 ? page_fault_oops+0x379/0x3e0 ? exc_page_fault+0x4f/0xa0 ? asm_exc_page_fault+0x22/0x30 ? __pfx_t7xx_ccmni_recv_skb+0x10/0x10 [mtk_t7xx (HASH:1400 7)] ? dev_gro_receive+0x3a/0x620 napi_gro_receive+0xad/0x170 t7xx_ccmni_recv_skb+0x48/0x70 [mtk_t7xx (HASH:1400 7)] t7xx_dpmaif_napi_rx_poll+0x590/0x800 [mtk_t7xx (HASH:1400 7)] net_rx_action+0x103/0x470 irq_exit_rcu+0x13a/0x310 sysvec_apic_timer_interrupt+0x56/0x90 </IRQ> Fixes: 5545b7b ("net: wwan: t7xx: Add NAPI support") Signed-off-by: Jinjian Song <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 051147c commit 1e0079e

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

drivers/net/wwan/t7xx/t7xx_netdev.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static void t7xx_ccmni_start(struct t7xx_ccmni_ctrl *ctlb)
172172
int i;
173173

174174
for (i = 0; i < ctlb->nic_dev_num; i++) {
175-
ccmni = ctlb->ccmni_inst[i];
175+
ccmni = READ_ONCE(ctlb->ccmni_inst[i]);
176176
if (!ccmni)
177177
continue;
178178

@@ -192,7 +192,7 @@ static void t7xx_ccmni_pre_stop(struct t7xx_ccmni_ctrl *ctlb)
192192
int i;
193193

194194
for (i = 0; i < ctlb->nic_dev_num; i++) {
195-
ccmni = ctlb->ccmni_inst[i];
195+
ccmni = READ_ONCE(ctlb->ccmni_inst[i]);
196196
if (!ccmni)
197197
continue;
198198

@@ -210,7 +210,7 @@ static void t7xx_ccmni_post_stop(struct t7xx_ccmni_ctrl *ctlb)
210210
t7xx_ccmni_disable_napi(ctlb);
211211

212212
for (i = 0; i < ctlb->nic_dev_num; i++) {
213-
ccmni = ctlb->ccmni_inst[i];
213+
ccmni = READ_ONCE(ctlb->ccmni_inst[i]);
214214
if (!ccmni)
215215
continue;
216216

@@ -302,7 +302,7 @@ static int t7xx_ccmni_wwan_newlink(void *ctxt, struct net_device *dev, u32 if_id
302302
ccmni->ctlb = ctlb;
303303
ccmni->dev = dev;
304304
atomic_set(&ccmni->usage, 0);
305-
ctlb->ccmni_inst[if_id] = ccmni;
305+
WRITE_ONCE(ctlb->ccmni_inst[if_id], ccmni);
306306

307307
ret = register_netdevice(dev);
308308
if (ret)
@@ -321,9 +321,10 @@ static void t7xx_ccmni_wwan_dellink(void *ctxt, struct net_device *dev, struct l
321321
if (if_id >= ARRAY_SIZE(ctlb->ccmni_inst))
322322
return;
323323

324-
if (WARN_ON(ctlb->ccmni_inst[if_id] != ccmni))
324+
if (WARN_ON(READ_ONCE(ctlb->ccmni_inst[if_id]) != ccmni))
325325
return;
326326

327+
WRITE_ONCE(ctlb->ccmni_inst[if_id], NULL);
327328
unregister_netdevice(dev);
328329
}
329330

@@ -419,7 +420,7 @@ static void t7xx_ccmni_recv_skb(struct t7xx_ccmni_ctrl *ccmni_ctlb, struct sk_bu
419420

420421
skb_cb = T7XX_SKB_CB(skb);
421422
netif_id = skb_cb->netif_idx;
422-
ccmni = ccmni_ctlb->ccmni_inst[netif_id];
423+
ccmni = READ_ONCE(ccmni_ctlb->ccmni_inst[netif_id]);
423424
if (!ccmni) {
424425
dev_kfree_skb(skb);
425426
return;
@@ -441,7 +442,7 @@ static void t7xx_ccmni_recv_skb(struct t7xx_ccmni_ctrl *ccmni_ctlb, struct sk_bu
441442

442443
static void t7xx_ccmni_queue_tx_irq_notify(struct t7xx_ccmni_ctrl *ctlb, int qno)
443444
{
444-
struct t7xx_ccmni *ccmni = ctlb->ccmni_inst[0];
445+
struct t7xx_ccmni *ccmni = READ_ONCE(ctlb->ccmni_inst[0]);
445446
struct netdev_queue *net_queue;
446447

447448
if (netif_running(ccmni->dev) && atomic_read(&ccmni->usage) > 0) {
@@ -453,7 +454,7 @@ static void t7xx_ccmni_queue_tx_irq_notify(struct t7xx_ccmni_ctrl *ctlb, int qno
453454

454455
static void t7xx_ccmni_queue_tx_full_notify(struct t7xx_ccmni_ctrl *ctlb, int qno)
455456
{
456-
struct t7xx_ccmni *ccmni = ctlb->ccmni_inst[0];
457+
struct t7xx_ccmni *ccmni = READ_ONCE(ctlb->ccmni_inst[0]);
457458
struct netdev_queue *net_queue;
458459

459460
if (atomic_read(&ccmni->usage) > 0) {
@@ -471,7 +472,7 @@ static void t7xx_ccmni_queue_state_notify(struct t7xx_pci_dev *t7xx_dev,
471472
if (ctlb->md_sta != MD_STATE_READY)
472473
return;
473474

474-
if (!ctlb->ccmni_inst[0]) {
475+
if (!READ_ONCE(ctlb->ccmni_inst[0])) {
475476
dev_warn(&t7xx_dev->pdev->dev, "No netdev registered yet\n");
476477
return;
477478
}

0 commit comments

Comments
 (0)