diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 049223df9beb1..dc4d87e004a0f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
bool ext_phy = mvif->phy != &dev->phy;
int ret, idx;
u32 addr;
+ u8 flags = MT76_WED_DEFAULT;
- idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+ !is_mt7915(&dev->mt76)) {
+ flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
+ MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
+ }
+
+ idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
if (idx < 0)
return -ENOSPC;
I'd prefer to replace the mt76_wcid_alloc flags argument with an explicit start offset argument.
@@ -1201,12 +1208,27 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,In order to update the code based on my latest changes and to fix potential race conditions on tx/rx packets during the transition, please change to this order:
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+ int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX;
if (enabled)
set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
else
clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+ !is_mt7915(&dev->mt76) &&
+ (msta->wcid.idx < min || msta->wcid.idx > max - 1)) {
+ struct ieee80211_sta *pre_sta;
+
+ pre_sta = kzalloc(sizeof(*sta) + sizeof(*msta), GFP_KERNEL);
+ mt76_sta_pre_rcu_remove(hw, vif, sta);
+ memmove(pre_sta, sta, sizeof(*sta) + sizeof(*msta));
+ mt7915_sta_add(hw, vif, sta);
+ synchronize_rcu();
+ mt7915_sta_remove(hw, vif, pre_sta);
+ kfree(pre_sta);
+ }
+
mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
}
1. copy the sta
2. allocate a new wcid
3. change the wcid index in the copied sta to the newly allocated wcid
4. call mcu functions on the duplicate sta for creating the new sta entry.
5. use rcu_assign_pointer to point dev->wcid[new_idx] at &msta->wcid
6. swap wcid index between real sta and duplicated sta
7. rcu_assign_pointer(dev->wcid[orig_idx], NULL)
8. synchronize_rcu()
9. call mcu functions to delete the duplicate sta's entry (points to old wcid after the swap)
10. free the duplicated sta
This should allow mgmt tx/rx to work while the sta is being migrated to the new wcid entry.
- Felix
Attachment:
OpenPGP_0xE3520CC91929C8E7.asc
Description: OpenPGP public key
Attachment:
OpenPGP_signature.asc
Description: OpenPGP digital signature