Hello Felix, Sorry to bother but any updates on this? I remember that you’ve agreed to take over this patch on IRC. Best regards, Shengyu > 在 2024年9月9日,00:27,Shengyu Qu <wiagn233@xxxxxxxxxxx> 写道: > > >> >>> 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. > > Hi Felix, > > I'm not really familiar with mt76 code, just a enthusiast that wants to > make WDS+WED working. So I'm not sure how to do this correctly... Maybe > it's better for you to take over this patch, sorry. > >>> @@ -1201,12 +1208,27 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, >>> { >>> 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); >>> } >>> >> 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: >> 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 > > Now, the mt7915_sta_set_4addr function looks like this(__mt76_wcid_alloc > not modified), do you think it's acceptable? > > static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > struct ieee80211_vif *vif, > struct ieee80211_sta *sta, > bool enabled) > { > 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; > struct ieee80211_sta *pre_sta; > u8 flags = MT76_WED_DEFAULT; > int temp_idx; > > if (enabled) > set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > else > clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > > if (!msta->wcid.sta) > return; > > if (mtk_wed_device_active(&dev->mt76.mmio.wed) && > !is_mt7915(&dev->mt76) && > (msta->wcid.idx < min || msta->wcid.idx > max - 1)) { > pre_sta = kzalloc(sizeof(*sta) + sizeof(*msta), GFP_KERNEL); > memmove(pre_sta, sta, sizeof(*sta) + sizeof(*msta)); > 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; > } > > temp_idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags); > ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = temp_idx; > mt7915_sta_add(hw, vif, pre_sta); > rcu_assign_pointer(dev->mt76.wcid[temp_idx], &msta->wcid); > temp_idx = msta->wcid.idx; > msta->wcid.idx = ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx; > ((struct mt7915_sta *)pre_sta->drv_priv)->wcid.idx = temp_idx; > rcu_assign_pointer(dev->mt76.wcid[temp_idx], NULL); > synchronize_rcu(); > mt7915_sta_remove(hw, vif, pre_sta); > kfree(pre_sta); > } > > mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); > } > > Best regards, > Shengyu > >> This should allow mgmt tx/rx to work while the sta is being migrated to the new wcid entry. >> - Felix > <OpenPGP_0xE3520CC91929C8E7.asc>