If the device is reset, suspended or unregistered within that window, the pending work can still run and access vif/bss data that may already be freed, or send MCU commands while the firmware is not available. Add cancel_delayed_work_sync(&dev->mlo_pm_work) in all relevant teardown and suspend paths: - mt7925_mac_reset_work() (chip reset recovery) - mt7925e_unregister_device() (PCIe unbind) - mt7925_pci_suspend() (PCIe bus suspend) - mt7925_suspend() (mac80211 suspend) - mt7925u_suspend() (USB bus / runtime suspend) This ensures the work is stopped before the device state becomes invalid. Assisted-by: kimi-cli:kimi-k2.7 code Assisted-by: atomcode:glm-5.2 #Reported-by Fixes: 276a568832577 ("wifi: mt76: mt7925: update the power-saving flow") Cc: stable@vger.kernel.org Signed-off-by: Wentao Guan --- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 1 + drivers/net/wireless/mediatek/mt76/mt7925/main.c | 1 + drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7925/usb.c | 1 + 4 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c index c47bd812b66b9..d56a846dec53e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -1307,6 +1307,7 @@ void mt7925_mac_reset_work(struct work_struct *work) cancel_delayed_work_sync(&dev->mphy.mac_work); cancel_delayed_work_sync(&pm->ps_work); + cancel_delayed_work_sync(&dev->mlo_pm_work); cancel_work_sync(&pm->wake_work); for (i = 0; i < 10; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index 73d3722739d0a..ab6c6565ca0f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -1602,6 +1602,7 @@ static int mt7925_suspend(struct ieee80211_hw *hw, cancel_delayed_work_sync(&phy->mt76->mac_work); cancel_delayed_work_sync(&dev->pm.ps_work); + cancel_delayed_work_sync(&dev->mlo_pm_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); mt792x_mutex_acquire(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c index c4161754c01df..cfa91af065b78 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c @@ -42,6 +42,7 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev) mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); cancel_delayed_work_sync(&pm->ps_work); + cancel_delayed_work_sync(&dev->mlo_pm_work); cancel_work_sync(&pm->wake_work); cancel_work_sync(&dev->reset_work); @@ -453,6 +454,7 @@ static int mt7925_pci_suspend(struct device *device) dev->hif_resumed = false; flush_work(&dev->reset_work); cancel_delayed_work_sync(&pm->ps_work); + cancel_delayed_work_sync(&dev->mlo_pm_work); cancel_work_sync(&pm->wake_work); mt7925_roc_abort_sync(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c index d9968f03856d8..7ba50c33cd32c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c @@ -251,6 +251,7 @@ static int mt7925u_suspend(struct usb_interface *intf, pm_message_t state) pm->suspended = true; dev->hif_resumed = false; flush_work(&dev->reset_work); + cancel_delayed_work_sync(&dev->mlo_pm_work); mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, false); ret = wait_event_timeout(dev->wait, -- 2.30.2