From: Charlie-cy Wu When neither MT7925_REGD_SUPPORTED nor MT792x_CHIP_CAP_11D_EN is set, mt7925_regd_change() calls mt7925_mcu_set_clc() directly. Its callers, mt7925_scan_work() and mt7925_mac_reset_work(), do not hold mt76.mutex, so __mt7925_mcu_set_clc() reads phy.power_type_user (written under the mutex from debugfs) and writes phy.clc_chan_conf without the lock, and sends MCU commands without waking the device. A concurrent 6G power mode change from debugfs can leave the CLC request and the 6G power tables sent to the firmware inconsistent. Wrap the fallback mt7925_mcu_set_clc() call with mt792x_mutex_acquire()/mt792x_mutex_release(). Neither caller holds the mutex already. Signed-off-by: Charlie-cy Wu --- drivers/net/wireless/mediatek/mt76/mt7925/regd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c index fac910406aa9..3060a9d93fe1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c @@ -564,7 +564,14 @@ int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2) } else if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN) { return regulatory_hint(wiphy, alpha2); } else { - return mt7925_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR, false); + int ret; + + /* callers (scan_work, reset_work) do not hold mt76.mutex */ + mt792x_mutex_acquire(dev); + ret = mt7925_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR, false); + mt792x_mutex_release(dev); + + return ret; } } EXPORT_SYMBOL_GPL(mt7925_regd_change); -- 2.18.0