Skip to content

Commit f86625a

Browse files
moore-brosnbd168
authored andcommitted
mt76: mt7921: fix invalid register access in wake_work
Make sure mt7921_pm_wake_work wouldn't be scheduled after the driver is in suspend mode to fix the following the kernel crash. [ 3515.390012] mt7921e 0000:01:00.0: calling pci_pm_suspend+0x0/0x22c @ 2869, parent: 0000:00:00.0 [ 3515.390015] mt7921e 0000:01:00.0: mt7921_pci_suspend + [ 3515.396395] anx7625 3-0058: anx7625_suspend+0x0/0x6c returned 0 after 0 usecs [ 3515.405965] mt7921e 0000:01:00.0: mt7921_pci_suspend - [ 3515.411336] usb 1-1.4: usb_dev_suspend+0x0/0x2c returned 0 after 1 usecs [ 3515.411513] SError Interrupt on CPU7, code 0xbe000011 -- SError [ 3515.411515] CPU: 7 PID: 2849 Comm: kworker/u16:27 Not tainted 5.4.114 #44 [ 3515.411516] Hardware name: MediaTek Asurada rev1 board (DT) [ 3515.411517] Workqueue: mt76 mt7921_pm_wake_work [mt7921e] [ 3515.411518] pstate: 80c00009 (Nzcv daif +PAN +UAO) [ 3515.411519] pc : mt76_mmio_rr+0x30/0xf0 [mt76] [ 3515.411520] lr : mt7921_rr+0x38/0x44 [mt7921e] [ 3515.411520] sp : ffffffc015813c50 [ 3515.411521] x29: ffffffc015813c50 x28: 0000000000000402 [ 3515.411522] x27: ffffffe5a2012138 x26: ffffffe5a1eea018 [ 3515.411524] x25: 00000000328be505 x24: 00000000000a0002 [ 3515.411525] x23: 0000000000000006 x22: ffffffbd29b7a300 [ 3515.411527] x21: ffffffbd29b7a300 x20: 00000000000e0010 [ 3515.411528] x19: 00000000eac08f43 x18: 0000000000000000 [ 3515.411529] x17: 0000000000000000 x16: ffffffe5a16b2914 [ 3515.411531] x15: 0000000000000010 x14: 0000000000000010 [ 3515.411532] x13: 00000000003dd3a2 x12: 0000000000010000 [ 3515.411533] x11: ffffffe597abec14 x10: 0000000000000010 [ 3515.411535] x9 : ffffffe597abeba8 x8 : ffffffc013ce0010 [ 3515.411536] x7 : 000000b2b5593519 x6 : 0000000000300000 [ 3515.411537] x5 : 0000000000000000 x4 : 0000000000000032 [ 3515.411539] x3 : 0000000000000000 x2 : 0000000000000004 [ 3515.411540] x1 : 00000000000e0010 x0 : ffffffbd29b7a300 [ 3515.411542] Kernel panic - not syncing: Asynchronous SError Interrupt [ 3515.411543] CPU: 7 PID: 2849 Comm: kworker/u16:27 Not tainted 5.4.114 #44 [ 3515.411544] Hardware name: MediaTek Asurada rev1 board (DT) [ 3515.411544] Workqueue: mt76 mt7921_pm_wake_work [mt7921e] [ 3515.411545] Call trace: [ 3515.411546] dump_backtrace+0x0/0x14c [ 3515.411546] show_stack+0x20/0x2c [ 3515.411547] dump_stack+0xa0/0xfc [ 3515.411548] panic+0x154/0x350 [ 3515.411548] panic+0x0/0x350 [ 3515.411549] arm64_serror_panic+0x78/0x84 [ 3515.411550] do_serror+0x0/0x118 [ 3515.411550] do_serror+0xa4/0x118 [ 3515.411551] el1_error+0x84/0xf8 [ 3515.411552] mt76_mmio_rr+0x30/0xf0 [mt76] [ 3515.411552] mt7921_rr+0x38/0x44 [mt7921e] [ 3515.411553] __mt76_poll_msec+0x5c/0x9c [mt76] [ 3515.411554] __mt7921_mcu_drv_pmctrl+0x50/0x94 [mt7921e] [ 3515.411555] mt7921_mcu_drv_pmctrl+0x38/0xb0 [mt7921e] [ 3515.411555] mt7921_pm_wake_work+0x34/0xd4 [mt7921e] [ 3515.411556] process_one_work+0x208/0x3c8 [ 3515.411557] worker_thread+0x23c/0x3e8 [ 3515.411557] kthread+0x144/0x178 [ 3515.411558] ret_from_fork+0x10/0x18 [ 3515.418831] SMP: stopping secondary CPUs [ 3515.418832] Kernel Offset: 0x2590c00000 from 0xffffffc010000000 [ 3515.418832] PHYS_OFFSET: 0xffffffc400000000 [ 3515.418833] CPU features: 0x080026,2a80aa18 [ 3515.418834] Memory Limit: none [DL] 00000000 00000000 010701 Fixes: 1d8efc7 ("mt76: mt7921: introduce Runtime PM support") Co-developed-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Sean Wang <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
1 parent f07ac38 commit f86625a

File tree

3 files changed

+24
-8
lines changed

3 files changed

+24
-8
lines changed

drivers/net/wireless/mediatek/mt76/mt76_connac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum {
4545

4646
struct mt76_connac_pm {
4747
bool enable;
48+
bool suspended;
4849

4950
spinlock_t txq_lock;
5051
struct {

drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
1717
if (!test_bit(MT76_STATE_PM, &phy->state))
1818
return 0;
1919

20+
if (pm->suspended)
21+
return 0;
22+
2023
queue_work(dev->wq, &pm->wake_work);
2124
if (!wait_event_timeout(pm->wait,
2225
!test_bit(MT76_STATE_PM, &phy->state),
@@ -40,6 +43,9 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy,
4043
if (!pm->enable)
4144
return;
4245

46+
if (pm->suspended)
47+
return;
48+
4349
pm->last_activity = jiffies;
4450

4551
if (!test_bit(MT76_STATE_PM, &phy->state)) {

drivers/net/wireless/mediatek/mt76/mt7921/pci.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,21 +188,26 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
188188
{
189189
struct mt76_dev *mdev = pci_get_drvdata(pdev);
190190
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
191+
struct mt76_connac_pm *pm = &dev->pm;
191192
bool hif_suspend;
192193
int i, err;
193194

194-
err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
195+
pm->suspended = true;
196+
cancel_delayed_work_sync(&pm->ps_work);
197+
cancel_work_sync(&pm->wake_work);
198+
199+
err = mt7921_mcu_drv_pmctrl(dev);
195200
if (err < 0)
196-
return err;
201+
goto restore_suspend;
197202

198203
hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
199204
if (hif_suspend) {
200205
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
201206
if (err)
202-
return err;
207+
goto restore_suspend;
203208
}
204209

205-
if (!dev->pm.enable)
210+
if (!pm->enable)
206211
mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
207212

208213
napi_disable(&mdev->tx_napi);
@@ -231,27 +236,30 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
231236

232237
err = mt7921_mcu_fw_pmctrl(dev);
233238
if (err)
234-
goto restore;
239+
goto restore_napi;
235240

236241
pci_save_state(pdev);
237242
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
238243
if (err)
239-
goto restore;
244+
goto restore_napi;
240245

241246
return 0;
242247

243-
restore:
248+
restore_napi:
244249
mt76_for_each_q_rx(mdev, i) {
245250
napi_enable(&mdev->napi[i]);
246251
}
247252
napi_enable(&mdev->tx_napi);
248253

249-
if (!dev->pm.enable)
254+
if (!pm->enable)
250255
mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
251256

252257
if (hif_suspend)
253258
mt76_connac_mcu_set_hif_suspend(mdev, false);
254259

260+
restore_suspend:
261+
pm->suspended = false;
262+
255263
return err;
256264
}
257265

@@ -261,6 +269,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
261269
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
262270
int i, err;
263271

272+
dev->pm.suspended = false;
264273
err = pci_set_power_state(pdev, PCI_D0);
265274
if (err)
266275
return err;

0 commit comments

Comments
 (0)