[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260120062854.126501-7-zac@zacbowling.com>
Date: Mon, 19 Jan 2026 22:28:49 -0800
From: Zac <zac@...bowling.com>
To: sean.wang@...nel.org
Cc: deren.wu@...iatek.com,
kvalo@...nel.org,
linux-kernel@...r.kernel.org,
linux-mediatek@...ts.infradead.org,
linux-wireless@...r.kernel.org,
lorenzo@...nel.org,
nbd@....name,
ryder.lee@...iatek.com,
sean.wang@...iatek.com,
stable@...r.kernel.org,
linux@...me.work,
zbowling@...il.com,
Zac Bowling <zac@...bowling.com>
Subject: [PATCH 06/11] wifi: mt76: mt7925: add mutex protection in critical paths
From: Zac Bowling <zac@...bowling.com>
Add proper mutex protection for mt7925 driver operations that access
hardware state without proper synchronization. This fixes race conditions
that can cause system instability during power management and recovery.
Fixes added:
1. mac.c: mt7925_mac_reset_work()
- Wrap ieee80211_iterate_active_interfaces() with mt792x_mutex
- The vif_connect_iter callback accesses hardware state
2. mac.c: mt7925_mac_sta_assoc()
- Wrap vif_connect_iter call with mutex protection
- Called during station association which races with PM
3. main.c: mt7925_set_runtime_pm()
- Add mutex protection around mt76_connac_pm_wake/sleep
- Runtime PM can race with other operations
4. main.c: mt7925_set_mlo_pm()
- Add mutex protection around MLO PM configuration
- Prevents races during MLO link setup/teardown
5. pci.c: mt7925_pci_resume()
- Add mutex protection around ieee80211_iterate_active_interfaces
- The vif iteration accesses hardware state that needs synchronization
These protections ensure consistent hardware state access during power
management transitions and recovery operations.
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 device")
Signed-off-by: Zac Bowling <zac@...bowling.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 2 ++
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 6 ++++--
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 4 ++++
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 184efe8afa10..06420ac6ed55 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -1331,9 +1331,11 @@ void mt7925_mac_reset_work(struct work_struct *work)
dev->hw_full_reset = false;
pm->suspended = false;
ieee80211_wake_queues(hw);
+ mt792x_mutex_acquire(dev);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7925_vif_connect_iter, NULL);
+ mt792x_mutex_release(dev);
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
mt7925_regd_change(&dev->phy, "00");
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 15d1b1b8d9f8..80ca5181150b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -755,9 +755,11 @@ void mt7925_set_runtime_pm(struct mt792x_dev *dev)
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
pm->enable = pm->enable_user && !monitor;
+ mt792x_mutex_acquire(dev);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7925_pm_interface_iter, dev);
+ mt792x_mutex_release(dev);
pm->ds_enable = pm->ds_enable_user && !monitor;
mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
}
@@ -1331,14 +1333,12 @@ mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS)
return;
- mt792x_mutex_acquire(dev);
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
bss_conf = mt792x_vif_to_bss_conf(vif, i);
if (!bss_conf)
continue;
mt7925_mcu_uni_bss_ps(dev, bss_conf);
}
- mt792x_mutex_release(dev);
}
void mt7925_mlo_pm_work(struct work_struct *work)
@@ -1347,9 +1347,11 @@ void mt7925_mlo_pm_work(struct work_struct *work)
mlo_pm_work.work);
struct ieee80211_hw *hw = mt76_hw(dev);
+ mt792x_mutex_acquire(dev);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7925_mlo_pm_iter, dev);
+ mt792x_mutex_release(dev);
}
void mt7925_scan_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index c4161754c01d..3a9e32a1759d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -455,7 +455,9 @@ static int mt7925_pci_suspend(struct device *device)
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
+ mt792x_mutex_acquire(dev);
mt7925_roc_abort_sync(dev);
+ mt792x_mutex_release(dev);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
@@ -582,10 +584,12 @@ static int _mt7925_pci_resume(struct device *device, bool restore)
}
/* restore previous ds setting */
+ mt792x_mutex_acquire(dev);
if (!pm->ds_enable)
mt7925_mcu_set_deep_sleep(dev, false);
mt7925_mcu_regd_update(dev, mdev->alpha2, dev->country_ie_env);
+ mt792x_mutex_release(dev);
failed:
pm->suspended = false;
--
2.52.0
Powered by blists - more mailing lists