mt76x02_mac_wcid_set_drop() changes one bit of an MT_WCID_DROP word, which holds the drop bits of 32 stations, with an unlocked read-modify-write. On MMIO devices it runs from the rx and tx paths, concurrently with station add and remove in process context. One update can thus overwrite another, and the hardware then discards all traffic of a station until its next powersave transition. Take mt76.lock around the update on MMIO devices. On USB devices, only station add and remove reach it. Register access there can sleep, and mt76.mutex already serialises both. Fixes: 7bc04215a66b ("mt76: add driver code for MT76x2e") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 158aa356b710..457767bbd8b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -166,7 +166,8 @@ void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, } EXPORT_SYMBOL_GPL(mt76x02_mac_wcid_setup); -void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) +static void +__mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) { u32 val = mt76_rr(dev, MT_WCID_DROP(idx)); u32 bit = MT_WCID_DROP_MASK(idx); @@ -176,6 +177,19 @@ void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); } +void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) +{ + /* USB register access can sleep, and mt76.mutex serialises USB callers */ + if (!mt76_is_mmio(&dev->mt76)) { + __mt76x02_mac_wcid_set_drop(dev, idx, drop); + return; + } + + spin_lock_bh(&dev->mt76.lock); + __mt76x02_mac_wcid_set_drop(dev, idx, drop); + spin_unlock_bh(&dev->mt76.lock); +} + static u16 mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, const struct ieee80211_tx_rate *rate, u8 *nss_val) -- 2.47.3