* [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled @ 2025-04-21 14:04 Shengyu Qu 2025-05-18 14:41 ` Shengyu Qu ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Shengyu Qu @ 2025-04-21 14:04 UTC (permalink / raw) To: nbd, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: Shengyu Qu, Sujuan Chen, Bo Jiao The current WED only supports 256 wcid, whereas mt7986 can support up to 512 entries, so firmware provides a rule to get sta_info by DA when wcid is set to 0x3ff by txd. Also, WED provides a register to overwrite txd wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set to 0xff by host driver. However, firmware is unable to get sta_info from DA as DA != RA for 4addr cases, so firmware and wifi host driver both use wcid (256 - 271) and (768 ~ 783) for sync up to get correct sta_info. Currently WDS+WED config is completely broken on MT7986/7981 devices if without this patch. Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> Tested-by: Sujuan Chen <sujuan.chen@mediatek.com> Co-developed-by: Bo Jiao <bo.jiao@mediatek.com> Signed-off-by: Bo Jiao <bo.jiao@mediatek.com> Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> Signed-off-by: Shengyu Qu <wiagn233@outlook.com> --- Changes since v1: - Drop duplicate setting in mmio - Reduce the patch size by redefining mt76_wcid_alloc Changes since v2: - Rework wds wcid getting flow Changes since v3: - Rebase to next-20240703 - Sync with downstream patch Changes since v4: - Rebase to next-20240802 Changes since v5: - Fixed build test error reported by robot - Rebase to next-20240805 Changes since v6: - Fix potential race conditions on tx/rx packets during the transition - Rebase to Felix's newest codebase Changes since v7: - Fix build fail Changes since v8: - Changed code as Shih advised Changes since v9: - Changed code as Shih advised - Moved mt76_wcid_alloc to mt76.h --- drivers/net/wireless/mediatek/mt76/mt76.h | 15 ++++++ .../net/wireless/mediatek/mt76/mt7915/main.c | 53 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++-- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 + drivers/net/wireless/mediatek/mt76/util.c | 37 +++++++++++-- drivers/net/wireless/mediatek/mt76/util.h | 2 +- 6 files changed, 115 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index d7cd467b812f..7f590854959e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -28,6 +28,9 @@ #define MT76_TOKEN_FREE_THR 64 +#define MT76_WED_WDS_MIN 256 +#define MT76_WED_WDS_MAX 272 + #define MT_QFLAG_WED_RING GENMASK(1, 0) #define MT_QFLAG_WED_TYPE GENMASK(4, 2) #define MT_QFLAG_WED BIT(5) @@ -73,6 +76,12 @@ enum mt76_wed_type { MT76_WED_RRO_Q_IND, }; +enum mt76_wed_state { + MT76_WED_DEFAULT, + MT76_WED_ACTIVE, + MT76_WED_WDS_ACTIVE, +}; + struct mt76_bus_ops { u32 (*rr)(struct mt76_dev *dev, u32 offset); void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); @@ -1169,6 +1178,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct net_device *netdev, enum tc_setup_type type, void *type_data); + +static inline int mt76_wcid_alloc(u32 *mask, int size) +{ + return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); +} + #ifdef CONFIG_NET_MEDIATEK_SOC_WED u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); int mt76_wed_offload_enable(struct mtk_wed_device *wed); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 3aa31c5cefa6..fcbf4f971026 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; bool ext_phy = mvif->phy != &dev->phy; + u8 flags = MT76_WED_DEFAULT; int idx; - 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; @@ -1271,6 +1278,11 @@ 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; + struct ieee80211_sta *pre_sta; + struct mt7915_sta *pre_msta; + u8 flags = MT76_WED_DEFAULT; + int tmp_idx; if (enabled) set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, 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 = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); + if (!pre_sta) + goto error_alloc; + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; + + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; + + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); + if (tmp_idx < 0) + goto error_wcid; + pre_msta->wcid.idx = (u16)tmp_idx; + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); + + tmp_idx = msta->wcid.idx; + msta->wcid.idx = pre_msta->wcid.idx; + pre_msta->wcid.idx = (u16)tmp_idx; + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); + + synchronize_rcu(); + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); + +error_wcid: + kfree(pre_sta); + } + +error_alloc: mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, if (!mtk_wed_device_active(wed)) return -ENODEV; - if (msta->wcid.idx > 0xff) + if (msta->wcid.idx > MT7915_WTBL_STA) return -EIO; path->type = DEV_PATH_MTK_WDMA; path->dev = ctx->dev; path->mtk_wdma.wdma_idx = wed->wdma_idx; path->mtk_wdma.bss = mvif->mt76.idx; - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; path->mtk_wdma.queue = phy != &dev->phy; + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || + is_mt7915(&dev->mt76)) + path->mtk_wdma.wcid = msta->wcid.idx; + else + path->mtk_wdma.wcid = 0x3ff; ctx->dev = NULL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 427542777abc..61a854d2c416 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2403,10 +2403,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) mt76_connac_mcu_del_wtbl_all(&dev->mt76); - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && - is_mt7915(&dev->mt76)) || - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + if (is_mt7915(&dev->mt76) || + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), + 0, 0, 0); + else + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), + MCU_WA_PARAM_WED_VERSION, + dev->mt76.mmio.wed.rev_id, 0); + if (ret) + return ret; + } +#endif ret = mt7915_mcu_set_mwds(dev, 1); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 086ad89ecd91..989f24cb49eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -278,6 +278,7 @@ enum { MCU_WA_PARAM_PDMA_RX = 0x04, MCU_WA_PARAM_CPU_UTIL = 0x0b, MCU_WA_PARAM_RED = 0x0e, + MCU_WA_PARAM_WED_VERSION = 0x32, MCU_WA_PARAM_RED_SETTING = 0x40, }; diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 95b3dc96e4c4..e80bef2b33a1 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, } EXPORT_SYMBOL_GPL(____mt76_poll_msec); -int mt76_wcid_alloc(u32 *mask, int size) +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) { + int max = MT76_WED_WDS_MAX; + int min = MT76_WED_WDS_MIN; int i, idx = 0, cur; for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) idx--; cur = i * 32 + idx; - if (cur >= size) + + switch (flag) { + case MT76_WED_ACTIVE: + if (cur >= min && cur < max) + continue; + + if (cur >= size) { + u32 end = max - min - 1; + + i = min / 32; + idx = ffs(~mask[i] & GENMASK(end, 0)); + if (!idx) + goto error; + idx--; + cur = min + idx; + } + break; + case MT76_WED_WDS_ACTIVE: + if (cur < min) + continue; + if (cur >= max) + goto error; + + break; + default: + if (cur >= size) + goto error; + break; + } mask[i] |= BIT(idx); return cur; } +error: return -1; } -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) { diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index 260965dde94c..fe95a847182e 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -27,7 +27,7 @@ enum { #define MT76_INCR(_var, _size) \ (_var = (((_var) + 1) % (_size))) -int mt76_wcid_alloc(u32 *mask, int size); +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); static inline void mt76_wcid_mask_set(u32 *mask, int idx) -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-04-21 14:04 [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu @ 2025-05-18 14:41 ` Shengyu Qu 2025-05-25 13:42 ` Shengyu Qu 2025-06-24 14:11 ` Shengyu Qu 2 siblings, 0 replies; 8+ messages in thread From: Shengyu Qu @ 2025-05-18 14:41 UTC (permalink / raw) To: nbd Cc: wiagn233, Sujuan Chen, Bo Jiao, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek [-- Attachment #1.1.1: Type: text/plain, Size: 11032 bytes --] Hi Felix, Do you think this patch is ok to merge? Best regards, Shengyu 在 2025/4/21 22:04, Shengyu Qu 写道: > The current WED only supports 256 wcid, whereas mt7986 can support up to > 512 entries, so firmware provides a rule to get sta_info by DA when wcid > is set to 0x3ff by txd. Also, WED provides a register to overwrite txd > wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set > to 0xff by host driver. > > However, firmware is unable to get sta_info from DA as DA != RA for > 4addr cases, so firmware and wifi host driver both use wcid (256 - 271) > and (768 ~ 783) for sync up to get correct sta_info. > > Currently WDS+WED config is completely broken on MT7986/7981 devices if > without this patch. > > Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> > Tested-by: Sujuan Chen <sujuan.chen@mediatek.com> > Co-developed-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> > Signed-off-by: Shengyu Qu <wiagn233@outlook.com> > --- > Changes since v1: > - Drop duplicate setting in mmio > - Reduce the patch size by redefining mt76_wcid_alloc > Changes since v2: > - Rework wds wcid getting flow > Changes since v3: > - Rebase to next-20240703 > - Sync with downstream patch > Changes since v4: > - Rebase to next-20240802 > Changes since v5: > - Fixed build test error reported by robot > - Rebase to next-20240805 > Changes since v6: > - Fix potential race conditions on tx/rx packets during the transition > - Rebase to Felix's newest codebase > Changes since v7: > - Fix build fail > Changes since v8: > - Changed code as Shih advised > Changes since v9: > - Changed code as Shih advised > - Moved mt76_wcid_alloc to mt76.h > --- > drivers/net/wireless/mediatek/mt76/mt76.h | 15 ++++++ > .../net/wireless/mediatek/mt76/mt7915/main.c | 53 +++++++++++++++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 + > drivers/net/wireless/mediatek/mt76/util.c | 37 +++++++++++-- > drivers/net/wireless/mediatek/mt76/util.h | 2 +- > 6 files changed, 115 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h > index d7cd467b812f..7f590854959e 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76.h > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h > @@ -28,6 +28,9 @@ > > #define MT76_TOKEN_FREE_THR 64 > > +#define MT76_WED_WDS_MIN 256 > +#define MT76_WED_WDS_MAX 272 > + > #define MT_QFLAG_WED_RING GENMASK(1, 0) > #define MT_QFLAG_WED_TYPE GENMASK(4, 2) > #define MT_QFLAG_WED BIT(5) > @@ -73,6 +76,12 @@ enum mt76_wed_type { > MT76_WED_RRO_Q_IND, > }; > > +enum mt76_wed_state { > + MT76_WED_DEFAULT, > + MT76_WED_ACTIVE, > + MT76_WED_WDS_ACTIVE, > +}; > + > struct mt76_bus_ops { > u32 (*rr)(struct mt76_dev *dev, u32 offset); > void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); > @@ -1169,6 +1178,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); > int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, > struct net_device *netdev, enum tc_setup_type type, > void *type_data); > + > +static inline int mt76_wcid_alloc(u32 *mask, int size) > +{ > + return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); > +} > + > #ifdef CONFIG_NET_MEDIATEK_SOC_WED > u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); > int mt76_wed_offload_enable(struct mtk_wed_device *wed); > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > index 3aa31c5cefa6..fcbf4f971026 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, > struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > bool ext_phy = mvif->phy != &dev->phy; > + u8 flags = MT76_WED_DEFAULT; > int idx; > > - 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; > > @@ -1271,6 +1278,11 @@ 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; > + struct ieee80211_sta *pre_sta; > + struct mt7915_sta *pre_msta; > + u8 flags = MT76_WED_DEFAULT; > + int tmp_idx; > > if (enabled) > set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > 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 = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); > + if (!pre_sta) > + goto error_alloc; > + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; > + > + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? > + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; > + > + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); > + if (tmp_idx < 0) > + goto error_wcid; > + pre_msta->wcid.idx = (u16)tmp_idx; > + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); > + > + tmp_idx = msta->wcid.idx; > + msta->wcid.idx = pre_msta->wcid.idx; > + pre_msta->wcid.idx = (u16)tmp_idx; > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); > + > + synchronize_rcu(); > + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); > + > +error_wcid: > + kfree(pre_sta); > + } > + > +error_alloc: > mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); > } > > @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, > if (!mtk_wed_device_active(wed)) > return -ENODEV; > > - if (msta->wcid.idx > 0xff) > + if (msta->wcid.idx > MT7915_WTBL_STA) > return -EIO; > > path->type = DEV_PATH_MTK_WDMA; > path->dev = ctx->dev; > path->mtk_wdma.wdma_idx = wed->wdma_idx; > path->mtk_wdma.bss = mvif->mt76.idx; > - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; > path->mtk_wdma.queue = phy != &dev->phy; > + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || > + is_mt7915(&dev->mt76)) > + path->mtk_wdma.wcid = msta->wcid.idx; > + else > + path->mtk_wdma.wcid = 0x3ff; > > ctx->dev = NULL; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > index 427542777abc..61a854d2c416 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > @@ -2403,10 +2403,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) > > mt76_connac_mcu_del_wtbl_all(&dev->mt76); > > - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && > - is_mt7915(&dev->mt76)) || > - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); > +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) > + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { > + if (is_mt7915(&dev->mt76) || > + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), > + 0, 0, 0); > + else > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), > + MCU_WA_PARAM_WED_VERSION, > + dev->mt76.mmio.wed.rev_id, 0); > + if (ret) > + return ret; > + } > +#endif > > ret = mt7915_mcu_set_mwds(dev, 1); > if (ret) > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > index 086ad89ecd91..989f24cb49eb 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > @@ -278,6 +278,7 @@ enum { > MCU_WA_PARAM_PDMA_RX = 0x04, > MCU_WA_PARAM_CPU_UTIL = 0x0b, > MCU_WA_PARAM_RED = 0x0e, > + MCU_WA_PARAM_WED_VERSION = 0x32, > MCU_WA_PARAM_RED_SETTING = 0x40, > }; > > diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c > index 95b3dc96e4c4..e80bef2b33a1 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.c > +++ b/drivers/net/wireless/mediatek/mt76/util.c > @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, > } > EXPORT_SYMBOL_GPL(____mt76_poll_msec); > > -int mt76_wcid_alloc(u32 *mask, int size) > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) > { > + int max = MT76_WED_WDS_MAX; > + int min = MT76_WED_WDS_MIN; > int i, idx = 0, cur; > > for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { > @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) > > idx--; > cur = i * 32 + idx; > - if (cur >= size) > + > + switch (flag) { > + case MT76_WED_ACTIVE: > + if (cur >= min && cur < max) > + continue; > + > + if (cur >= size) { > + u32 end = max - min - 1; > + > + i = min / 32; > + idx = ffs(~mask[i] & GENMASK(end, 0)); > + if (!idx) > + goto error; > + idx--; > + cur = min + idx; > + } > + > break; > + case MT76_WED_WDS_ACTIVE: > + if (cur < min) > + continue; > + if (cur >= max) > + goto error; > + > + break; > + default: > + if (cur >= size) > + goto error; > + break; > + } > > mask[i] |= BIT(idx); > return cur; > } > > +error: > return -1; > } > -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); > +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); > > int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) > { > diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h > index 260965dde94c..fe95a847182e 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.h > +++ b/drivers/net/wireless/mediatek/mt76/util.h > @@ -27,7 +27,7 @@ enum { > #define MT76_INCR(_var, _size) \ > (_var = (((_var) + 1) % (_size))) > > -int mt76_wcid_alloc(u32 *mask, int size); > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); > > static inline void > mt76_wcid_mask_set(u32 *mask, int idx) [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 6977 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-04-21 14:04 [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu 2025-05-18 14:41 ` Shengyu Qu @ 2025-05-25 13:42 ` Shengyu Qu 2025-06-24 14:11 ` Shengyu Qu 2 siblings, 0 replies; 8+ messages in thread From: Shengyu Qu @ 2025-05-25 13:42 UTC (permalink / raw) To: nbd, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: wiagn233, Sujuan Chen, Bo Jiao [-- Attachment #1.1.1: Type: text/plain, Size: 10965 bytes --] Ping again. 在 2025/4/21 22:04, Shengyu Qu 写道: > The current WED only supports 256 wcid, whereas mt7986 can support up to > 512 entries, so firmware provides a rule to get sta_info by DA when wcid > is set to 0x3ff by txd. Also, WED provides a register to overwrite txd > wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set > to 0xff by host driver. > > However, firmware is unable to get sta_info from DA as DA != RA for > 4addr cases, so firmware and wifi host driver both use wcid (256 - 271) > and (768 ~ 783) for sync up to get correct sta_info. > > Currently WDS+WED config is completely broken on MT7986/7981 devices if > without this patch. > > Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> > Tested-by: Sujuan Chen <sujuan.chen@mediatek.com> > Co-developed-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> > Signed-off-by: Shengyu Qu <wiagn233@outlook.com> > --- > Changes since v1: > - Drop duplicate setting in mmio > - Reduce the patch size by redefining mt76_wcid_alloc > Changes since v2: > - Rework wds wcid getting flow > Changes since v3: > - Rebase to next-20240703 > - Sync with downstream patch > Changes since v4: > - Rebase to next-20240802 > Changes since v5: > - Fixed build test error reported by robot > - Rebase to next-20240805 > Changes since v6: > - Fix potential race conditions on tx/rx packets during the transition > - Rebase to Felix's newest codebase > Changes since v7: > - Fix build fail > Changes since v8: > - Changed code as Shih advised > Changes since v9: > - Changed code as Shih advised > - Moved mt76_wcid_alloc to mt76.h > --- > drivers/net/wireless/mediatek/mt76/mt76.h | 15 ++++++ > .../net/wireless/mediatek/mt76/mt7915/main.c | 53 +++++++++++++++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 + > drivers/net/wireless/mediatek/mt76/util.c | 37 +++++++++++-- > drivers/net/wireless/mediatek/mt76/util.h | 2 +- > 6 files changed, 115 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h > index d7cd467b812f..7f590854959e 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76.h > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h > @@ -28,6 +28,9 @@ > > #define MT76_TOKEN_FREE_THR 64 > > +#define MT76_WED_WDS_MIN 256 > +#define MT76_WED_WDS_MAX 272 > + > #define MT_QFLAG_WED_RING GENMASK(1, 0) > #define MT_QFLAG_WED_TYPE GENMASK(4, 2) > #define MT_QFLAG_WED BIT(5) > @@ -73,6 +76,12 @@ enum mt76_wed_type { > MT76_WED_RRO_Q_IND, > }; > > +enum mt76_wed_state { > + MT76_WED_DEFAULT, > + MT76_WED_ACTIVE, > + MT76_WED_WDS_ACTIVE, > +}; > + > struct mt76_bus_ops { > u32 (*rr)(struct mt76_dev *dev, u32 offset); > void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); > @@ -1169,6 +1178,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); > int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, > struct net_device *netdev, enum tc_setup_type type, > void *type_data); > + > +static inline int mt76_wcid_alloc(u32 *mask, int size) > +{ > + return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); > +} > + > #ifdef CONFIG_NET_MEDIATEK_SOC_WED > u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); > int mt76_wed_offload_enable(struct mtk_wed_device *wed); > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > index 3aa31c5cefa6..fcbf4f971026 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, > struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > bool ext_phy = mvif->phy != &dev->phy; > + u8 flags = MT76_WED_DEFAULT; > int idx; > > - 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; > > @@ -1271,6 +1278,11 @@ 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; > + struct ieee80211_sta *pre_sta; > + struct mt7915_sta *pre_msta; > + u8 flags = MT76_WED_DEFAULT; > + int tmp_idx; > > if (enabled) > set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > 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 = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); > + if (!pre_sta) > + goto error_alloc; > + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; > + > + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? > + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; > + > + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); > + if (tmp_idx < 0) > + goto error_wcid; > + pre_msta->wcid.idx = (u16)tmp_idx; > + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); > + > + tmp_idx = msta->wcid.idx; > + msta->wcid.idx = pre_msta->wcid.idx; > + pre_msta->wcid.idx = (u16)tmp_idx; > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); > + > + synchronize_rcu(); > + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); > + > +error_wcid: > + kfree(pre_sta); > + } > + > +error_alloc: > mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); > } > > @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, > if (!mtk_wed_device_active(wed)) > return -ENODEV; > > - if (msta->wcid.idx > 0xff) > + if (msta->wcid.idx > MT7915_WTBL_STA) > return -EIO; > > path->type = DEV_PATH_MTK_WDMA; > path->dev = ctx->dev; > path->mtk_wdma.wdma_idx = wed->wdma_idx; > path->mtk_wdma.bss = mvif->mt76.idx; > - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; > path->mtk_wdma.queue = phy != &dev->phy; > + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || > + is_mt7915(&dev->mt76)) > + path->mtk_wdma.wcid = msta->wcid.idx; > + else > + path->mtk_wdma.wcid = 0x3ff; > > ctx->dev = NULL; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > index 427542777abc..61a854d2c416 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > @@ -2403,10 +2403,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) > > mt76_connac_mcu_del_wtbl_all(&dev->mt76); > > - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && > - is_mt7915(&dev->mt76)) || > - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); > +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) > + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { > + if (is_mt7915(&dev->mt76) || > + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), > + 0, 0, 0); > + else > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), > + MCU_WA_PARAM_WED_VERSION, > + dev->mt76.mmio.wed.rev_id, 0); > + if (ret) > + return ret; > + } > +#endif > > ret = mt7915_mcu_set_mwds(dev, 1); > if (ret) > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > index 086ad89ecd91..989f24cb49eb 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > @@ -278,6 +278,7 @@ enum { > MCU_WA_PARAM_PDMA_RX = 0x04, > MCU_WA_PARAM_CPU_UTIL = 0x0b, > MCU_WA_PARAM_RED = 0x0e, > + MCU_WA_PARAM_WED_VERSION = 0x32, > MCU_WA_PARAM_RED_SETTING = 0x40, > }; > > diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c > index 95b3dc96e4c4..e80bef2b33a1 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.c > +++ b/drivers/net/wireless/mediatek/mt76/util.c > @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, > } > EXPORT_SYMBOL_GPL(____mt76_poll_msec); > > -int mt76_wcid_alloc(u32 *mask, int size) > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) > { > + int max = MT76_WED_WDS_MAX; > + int min = MT76_WED_WDS_MIN; > int i, idx = 0, cur; > > for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { > @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) > > idx--; > cur = i * 32 + idx; > - if (cur >= size) > + > + switch (flag) { > + case MT76_WED_ACTIVE: > + if (cur >= min && cur < max) > + continue; > + > + if (cur >= size) { > + u32 end = max - min - 1; > + > + i = min / 32; > + idx = ffs(~mask[i] & GENMASK(end, 0)); > + if (!idx) > + goto error; > + idx--; > + cur = min + idx; > + } > + > break; > + case MT76_WED_WDS_ACTIVE: > + if (cur < min) > + continue; > + if (cur >= max) > + goto error; > + > + break; > + default: > + if (cur >= size) > + goto error; > + break; > + } > > mask[i] |= BIT(idx); > return cur; > } > > +error: > return -1; > } > -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); > +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); > > int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) > { > diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h > index 260965dde94c..fe95a847182e 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.h > +++ b/drivers/net/wireless/mediatek/mt76/util.h > @@ -27,7 +27,7 @@ enum { > #define MT76_INCR(_var, _size) \ > (_var = (((_var) + 1) % (_size))) > > -int mt76_wcid_alloc(u32 *mask, int size); > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); > > static inline void > mt76_wcid_mask_set(u32 *mask, int idx) [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 6977 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 840 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-04-21 14:04 [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu 2025-05-18 14:41 ` Shengyu Qu 2025-05-25 13:42 ` Shengyu Qu @ 2025-06-24 14:11 ` Shengyu Qu 2025-06-25 10:18 ` Felix Fietkau 2 siblings, 1 reply; 8+ messages in thread From: Shengyu Qu @ 2025-06-24 14:11 UTC (permalink / raw) To: nbd, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: wiagn233, Sujuan Chen, Bo Jiao [-- Attachment #1.1.1: Type: text/plain, Size: 11197 bytes --] Hi Felix, Please, tell me if this patch needs any polishing. I really don't know why this patch still not get merged after such a long time(and 2x resend), especially it already got a Reviewed-by and is a bugfix. Best regards, Shengyu 在 2025/4/21 22:04, Shengyu Qu 写道: > The current WED only supports 256 wcid, whereas mt7986 can support up to > 512 entries, so firmware provides a rule to get sta_info by DA when wcid > is set to 0x3ff by txd. Also, WED provides a register to overwrite txd > wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set > to 0xff by host driver. > > However, firmware is unable to get sta_info from DA as DA != RA for > 4addr cases, so firmware and wifi host driver both use wcid (256 - 271) > and (768 ~ 783) for sync up to get correct sta_info. > > Currently WDS+WED config is completely broken on MT7986/7981 devices if > without this patch. > > Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> > Tested-by: Sujuan Chen <sujuan.chen@mediatek.com> > Co-developed-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Bo Jiao <bo.jiao@mediatek.com> > Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> > Signed-off-by: Shengyu Qu <wiagn233@outlook.com> > --- > Changes since v1: > - Drop duplicate setting in mmio > - Reduce the patch size by redefining mt76_wcid_alloc > Changes since v2: > - Rework wds wcid getting flow > Changes since v3: > - Rebase to next-20240703 > - Sync with downstream patch > Changes since v4: > - Rebase to next-20240802 > Changes since v5: > - Fixed build test error reported by robot > - Rebase to next-20240805 > Changes since v6: > - Fix potential race conditions on tx/rx packets during the transition > - Rebase to Felix's newest codebase > Changes since v7: > - Fix build fail > Changes since v8: > - Changed code as Shih advised > Changes since v9: > - Changed code as Shih advised > - Moved mt76_wcid_alloc to mt76.h > --- > drivers/net/wireless/mediatek/mt76/mt76.h | 15 ++++++ > .../net/wireless/mediatek/mt76/mt7915/main.c | 53 +++++++++++++++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++-- > .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 + > drivers/net/wireless/mediatek/mt76/util.c | 37 +++++++++++-- > drivers/net/wireless/mediatek/mt76/util.h | 2 +- > 6 files changed, 115 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h > index d7cd467b812f..7f590854959e 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76.h > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h > @@ -28,6 +28,9 @@ > > #define MT76_TOKEN_FREE_THR 64 > > +#define MT76_WED_WDS_MIN 256 > +#define MT76_WED_WDS_MAX 272 > + > #define MT_QFLAG_WED_RING GENMASK(1, 0) > #define MT_QFLAG_WED_TYPE GENMASK(4, 2) > #define MT_QFLAG_WED BIT(5) > @@ -73,6 +76,12 @@ enum mt76_wed_type { > MT76_WED_RRO_Q_IND, > }; > > +enum mt76_wed_state { > + MT76_WED_DEFAULT, > + MT76_WED_ACTIVE, > + MT76_WED_WDS_ACTIVE, > +}; > + > struct mt76_bus_ops { > u32 (*rr)(struct mt76_dev *dev, u32 offset); > void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); > @@ -1169,6 +1178,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); > int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, > struct net_device *netdev, enum tc_setup_type type, > void *type_data); > + > +static inline int mt76_wcid_alloc(u32 *mask, int size) > +{ > + return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); > +} > + > #ifdef CONFIG_NET_MEDIATEK_SOC_WED > u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); > int mt76_wed_offload_enable(struct mtk_wed_device *wed); > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > index 3aa31c5cefa6..fcbf4f971026 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, > struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > bool ext_phy = mvif->phy != &dev->phy; > + u8 flags = MT76_WED_DEFAULT; > int idx; > > - 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; > > @@ -1271,6 +1278,11 @@ 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; > + struct ieee80211_sta *pre_sta; > + struct mt7915_sta *pre_msta; > + u8 flags = MT76_WED_DEFAULT; > + int tmp_idx; > > if (enabled) > set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > 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 = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); > + if (!pre_sta) > + goto error_alloc; > + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; > + > + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? > + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; > + > + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); > + if (tmp_idx < 0) > + goto error_wcid; > + pre_msta->wcid.idx = (u16)tmp_idx; > + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); > + > + tmp_idx = msta->wcid.idx; > + msta->wcid.idx = pre_msta->wcid.idx; > + pre_msta->wcid.idx = (u16)tmp_idx; > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); > + > + synchronize_rcu(); > + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); > + > +error_wcid: > + kfree(pre_sta); > + } > + > +error_alloc: > mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); > } > > @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, > if (!mtk_wed_device_active(wed)) > return -ENODEV; > > - if (msta->wcid.idx > 0xff) > + if (msta->wcid.idx > MT7915_WTBL_STA) > return -EIO; > > path->type = DEV_PATH_MTK_WDMA; > path->dev = ctx->dev; > path->mtk_wdma.wdma_idx = wed->wdma_idx; > path->mtk_wdma.bss = mvif->mt76.idx; > - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; > path->mtk_wdma.queue = phy != &dev->phy; > + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || > + is_mt7915(&dev->mt76)) > + path->mtk_wdma.wcid = msta->wcid.idx; > + else > + path->mtk_wdma.wcid = 0x3ff; > > ctx->dev = NULL; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > index 427542777abc..61a854d2c416 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > @@ -2403,10 +2403,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) > > mt76_connac_mcu_del_wtbl_all(&dev->mt76); > > - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && > - is_mt7915(&dev->mt76)) || > - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); > +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) > + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { > + if (is_mt7915(&dev->mt76) || > + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), > + 0, 0, 0); > + else > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), > + MCU_WA_PARAM_WED_VERSION, > + dev->mt76.mmio.wed.rev_id, 0); > + if (ret) > + return ret; > + } > +#endif > > ret = mt7915_mcu_set_mwds(dev, 1); > if (ret) > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > index 086ad89ecd91..989f24cb49eb 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > @@ -278,6 +278,7 @@ enum { > MCU_WA_PARAM_PDMA_RX = 0x04, > MCU_WA_PARAM_CPU_UTIL = 0x0b, > MCU_WA_PARAM_RED = 0x0e, > + MCU_WA_PARAM_WED_VERSION = 0x32, > MCU_WA_PARAM_RED_SETTING = 0x40, > }; > > diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c > index 95b3dc96e4c4..e80bef2b33a1 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.c > +++ b/drivers/net/wireless/mediatek/mt76/util.c > @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, > } > EXPORT_SYMBOL_GPL(____mt76_poll_msec); > > -int mt76_wcid_alloc(u32 *mask, int size) > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) > { > + int max = MT76_WED_WDS_MAX; > + int min = MT76_WED_WDS_MIN; > int i, idx = 0, cur; > > for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { > @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) > > idx--; > cur = i * 32 + idx; > - if (cur >= size) > + > + switch (flag) { > + case MT76_WED_ACTIVE: > + if (cur >= min && cur < max) > + continue; > + > + if (cur >= size) { > + u32 end = max - min - 1; > + > + i = min / 32; > + idx = ffs(~mask[i] & GENMASK(end, 0)); > + if (!idx) > + goto error; > + idx--; > + cur = min + idx; > + } > + > break; > + case MT76_WED_WDS_ACTIVE: > + if (cur < min) > + continue; > + if (cur >= max) > + goto error; > + > + break; > + default: > + if (cur >= size) > + goto error; > + break; > + } > > mask[i] |= BIT(idx); > return cur; > } > > +error: > return -1; > } > -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); > +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); > > int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) > { > diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h > index 260965dde94c..fe95a847182e 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.h > +++ b/drivers/net/wireless/mediatek/mt76/util.h > @@ -27,7 +27,7 @@ enum { > #define MT76_INCR(_var, _size) \ > (_var = (((_var) + 1) % (_size))) > > -int mt76_wcid_alloc(u32 *mask, int size); > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); > > static inline void > mt76_wcid_mask_set(u32 *mask, int idx) [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 6977 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 840 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-06-24 14:11 ` Shengyu Qu @ 2025-06-25 10:18 ` Felix Fietkau 2025-06-25 11:00 ` Felix Fietkau 0 siblings, 1 reply; 8+ messages in thread From: Felix Fietkau @ 2025-06-25 10:18 UTC (permalink / raw) To: Shengyu Qu, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: Sujuan Chen, Bo Jiao On 24.06.25 16:11, Shengyu Qu wrote: > Hi Felix, > > Please, tell me if this patch needs any polishing. I really don't know > why this patch still not get merged after such a long time(and 2x > resend), especially it already got a Reviewed-by and is a bugfix. Hi Shengyu, sorry it took such a long time for me to take a look at this patch. I don't see how it can even work properly in its current form, because of at least one bug: When switching from non-wds to wds mode, the code calls mt7915_mac_sta_add in order to create the new sta. However, after changes that I made a while back, this function does not actually upload the station to the MCU anymore, since it is called on the NOTEXIST->NONE transition before assoc. Without corresponding ASSOC/AUTHORIZE events (handled by mt7915_mac_sta_event), the firmware doesn't get any data for the new wcid. That said, I finally got around to starting to rework your patch myself. I will let you know when I have something ready for testing, hopefully later today. - Felix ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-06-25 10:18 ` Felix Fietkau @ 2025-06-25 11:00 ` Felix Fietkau 2025-06-25 17:25 ` Shengyu Qu 0 siblings, 1 reply; 8+ messages in thread From: Felix Fietkau @ 2025-06-25 11:00 UTC (permalink / raw) To: Shengyu Qu, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: Sujuan Chen, Bo Jiao On 25.06.25 12:18, Felix Fietkau wrote: > On 24.06.25 16:11, Shengyu Qu wrote: >> Hi Felix, >> >> Please, tell me if this patch needs any polishing. I really don't know >> why this patch still not get merged after such a long time(and 2x >> resend), especially it already got a Reviewed-by and is a bugfix. > > Hi Shengyu, > > sorry it took such a long time for me to take a look at this patch. > I don't see how it can even work properly in its current form, because > of at least one bug: > > When switching from non-wds to wds mode, the code calls > mt7915_mac_sta_add in order to create the new sta. However, after > changes that I made a while back, this function does not actually upload > the station to the MCU anymore, since it is called on the NOTEXIST->NONE > transition before assoc. Without corresponding ASSOC/AUTHORIZE events > (handled by mt7915_mac_sta_event), the firmware doesn't get any data for > the new wcid. > > That said, I finally got around to starting to rework your patch myself. > I will let you know when I have something ready for testing, hopefully > later today. Here's my first draft: --- diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 14927a92f9d1..f1d1b0ebd074 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -28,6 +28,9 @@ #define MT76_TOKEN_FREE_THR 64 +#define MT76_WED_WDS_MIN 256 +#define MT76_WED_WDS_MAX 272 + #define MT_QFLAG_WED_RING GENMASK(1, 0) #define MT_QFLAG_WED_TYPE GENMASK(4, 2) #define MT_QFLAG_WED BIT(5) @@ -1181,6 +1184,7 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct net_device *netdev, enum tc_setup_type type, void *type_data); + #ifdef CONFIG_NET_MEDIATEK_SOC_WED u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); int mt76_wed_offload_enable(struct mtk_wed_device *wed); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index b287b7d9394e..ec2287459587 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -1385,7 +1385,7 @@ static ssize_t mt7915_sta_fixed_rate_set(struct file *file, out: vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, field); + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, &phy, field); if (ret) return -EFAULT; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 9400e4af2a04..e3e65848a17f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1991,7 +1991,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | IEEE80211_RC_NSS_CHANGED | IEEE80211_RC_BW_CHANGED)) - mt7915_mcu_add_rate_ctrl(dev, vif, sta, true); + mt7915_mcu_add_rate_ctrl(dev, vif, sta, &msta->wcid, true); if (changed & IEEE80211_RC_SMPS_CHANGED) mt7915_mcu_add_smps(dev, vif, sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index fe0639c14bf9..0227ea8665f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -747,7 +747,13 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, bool ext_phy = mvif->phy != &dev->phy; int idx; - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + !is_mt7915(&dev->mt76) && + test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) + idx = __mt76_wcid_alloc(mdev->wcid_mask, MT76_WED_WDS_MIN, + MT76_WED_WDS_MAX); + else + idx = mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA); if (idx < 0) return -ENOSPC; @@ -836,7 +842,7 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30); mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0); - ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); + ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, &msta->wcid, false); if (ret) return ret; @@ -1267,6 +1273,40 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } +static void mt7915_sta_wed_set_4addr(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX; + int idx, prev_idx = msta->wcid.idx; + struct mt76_wcid wcid = msta->wcid; + int state; + + if (!is_mt7915(&dev->mt76)) + return; + + if (msta->wcid.idx >= min && msta->wcid.idx < max) + return; + + idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, min, max); + if (idx < 0) + return; + + wcid.idx = idx; + state = msta->wcid.sta ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT; + __mt7915_mcu_add_sta(dev, vif, sta, &wcid, state, true); + mt7915_mcu_add_rate_ctrl(dev, vif, sta, &wcid, false); + rcu_assign_pointer(dev->mt76.wcid[idx], &msta->wcid); + msta->wcid.idx = idx; + + synchronize_rcu(); + + rcu_assign_pointer(dev->mt76.wcid[prev_idx], NULL); + mt76_wcid_mask_clear(dev->mt76.wcid_mask, prev_idx); + wcid.idx = prev_idx; + __mt7915_mcu_add_sta(dev, vif, sta, &wcid, CONN_STATE_DISCONNECT, false); +} + static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1280,6 +1320,9 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, else clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && enabled) + mt7915_sta_wed_set_4addr(dev, vif, sta); + if (!msta->wcid.sta) return; @@ -1729,15 +1772,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, if (!mtk_wed_device_active(wed)) return -ENODEV; - if (msta->wcid.idx > 0xff) + if (msta->wcid.idx > MT7915_WTBL_STA) return -EIO; path->type = DEV_PATH_MTK_WDMA; path->dev = ctx->dev; path->mtk_wdma.wdma_idx = wed->wdma_idx; path->mtk_wdma.bss = mvif->mt76.idx; - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; path->mtk_wdma.queue = phy != &dev->phy; + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || + is_mt7915(&dev->mt76)) + path->mtk_wdma.wcid = msta->wcid.idx; + else + path->mtk_wdma.wcid = 0x3ff; ctx->dev = NULL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index cf948628e588..26497b580eb6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1359,6 +1359,7 @@ mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode smps) int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct mt76_wcid *wcid, void *data, u32 field) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; @@ -1430,7 +1431,7 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, if (ret) return ret; - return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, NULL, + return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, NULL, RATE_PARAM_MMPS_UPDATE); } @@ -1439,17 +1440,19 @@ mt7915_mcu_set_spe_idx(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt76_phy *mphy = mvif->phy->mt76; u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask); - return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &spe_idx, - RATE_PARAM_SPE_UPDATE); + return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, + &spe_idx, RATE_PARAM_SPE_UPDATE); } static int mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + struct mt76_wcid *wcid) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; @@ -1497,7 +1500,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, /* fixed single rate */ if (nrates == 1) { - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, RATE_PARAM_FIXED_MCS); if (ret) return ret; @@ -1519,7 +1522,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, else mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, RATE_PARAM_FIXED_GI); if (ret) return ret; @@ -1527,7 +1530,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, /* fixed HE_LTF */ if (mask->control[band].he_ltf != GENMASK(7, 0)) { - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, RATE_PARAM_FIXED_HE_LTF); if (ret) return ret; @@ -1640,15 +1643,14 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, } int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool changed) + struct ieee80211_sta *sta, struct mt76_wcid *wcid, + bool changed) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct sk_buff *skb; int ret; - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, wcid); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -1673,7 +1675,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, * and updates as peer fixed rate parameters, which overrides * sta_rec_ra and firmware rate control algorithm. */ - return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta); + return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta, wcid); } static int @@ -1704,8 +1706,9 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif, sizeof(req), true); } -int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, int conn_state, bool newly) +int __mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct mt76_wcid *wcid, + int conn_state, bool newly) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_link_sta *link_sta; @@ -1715,9 +1718,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; link_sta = sta ? &sta->deflink : NULL; + if (!wcid) + wcid = &msta->wcid; - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, wcid); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2413,10 +2417,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) mt76_connac_mcu_del_wtbl_all(&dev->mt76); - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && - is_mt7915(&dev->mt76)) || - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + if (is_mt7915(&dev->mt76) || + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), + 0, 0, 0); + else + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), + MCU_WA_PARAM_WED_VERSION, + dev->mt76.mmio.wed.rev_id, 0); + if (ret) + return ret; + } +#endif ret = mt7915_mcu_set_mwds(dev, 1); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 086ad89ecd91..989f24cb49eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -278,6 +278,7 @@ enum { MCU_WA_PARAM_PDMA_RX = 0x04, MCU_WA_PARAM_CPU_UTIL = 0x0b, MCU_WA_PARAM_RED = 0x0e, + MCU_WA_PARAM_WED_VERSION = 0x32, MCU_WA_PARAM_RED_SETTING = 0x40, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 2e94347c46d6..c781058a416f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -455,8 +455,16 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool enable); int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable); -int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, int conn_state, bool newly); +int __mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct mt76_wcid *wcid, + int conn_state, bool newly); +static inline int +mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, int conn_state, bool newly) +{ + return __mt7915_mcu_add_sta(dev, vif, sta, NULL, conn_state, newly); +} + int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool add); @@ -472,7 +480,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_he_obss_pd *he_obss_pd); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool changed); + struct ieee80211_sta *sta, struct mt76_wcid *wcid, + bool changed); int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7915_set_channel(struct mt76_phy *mphy); @@ -482,6 +491,7 @@ int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req); int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct mt76_wcid *wcid, void *data, u32 field); int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf); diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 95b3dc96e4c4..9fa60d380ede 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -42,12 +42,19 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, } EXPORT_SYMBOL_GPL(____mt76_poll_msec); -int mt76_wcid_alloc(u32 *mask, int size) +int __mt76_wcid_alloc(u32 *mask, int min, int size) { + u32 min_mask = ~0; int i, idx = 0, cur; + mask += min / 32; + min %= 32; + if (min > 0) + min_mask = ~((1 << min) - 1); + for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { - idx = ffs(~mask[i]); + idx = ffs(~mask[i] & min_mask); + min_mask = ~0; if (!idx) continue; @@ -62,7 +69,7 @@ int mt76_wcid_alloc(u32 *mask, int size) return -1; } -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) { diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index 260965dde94c..bca2893f980e 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -27,7 +27,12 @@ enum { #define MT76_INCR(_var, _size) \ (_var = (((_var) + 1) % (_size))) -int mt76_wcid_alloc(u32 *mask, int size); +int __mt76_wcid_alloc(u32 *mask, int min, int size); + +static inline int mt76_wcid_alloc(u32 *mask, int size) +{ + return __mt76_wcid_alloc(mask, 0, size); +} static inline void mt76_wcid_mask_set(u32 *mask, int idx) -- 2.49.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled 2025-06-25 11:00 ` Felix Fietkau @ 2025-06-25 17:25 ` Shengyu Qu 0 siblings, 0 replies; 8+ messages in thread From: Shengyu Qu @ 2025-06-25 17:25 UTC (permalink / raw) To: Felix Fietkau, pkshih, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, christophe.jaillet, greearb, howard-yh.hsu, StanleyYP.Wang, deren.wu, chui-hao.chiu, quic_adisi, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: wiagn233, Sujuan Chen, Bo Jiao [-- Attachment #1.1.1: Type: text/plain, Size: 21543 bytes --] Hi Felix, Thanks for reply. Sadly I don't have time to test this patch either. But I think you can find someone to help testing it here: https://github.com/openwrt/openwrt/issues/14680 Best regards, Shengyu 在 2025/6/25 19:00, Felix Fietkau 写道: > On 25.06.25 12:18, Felix Fietkau wrote: >> On 24.06.25 16:11, Shengyu Qu wrote: >>> Hi Felix, >>> >>> Please, tell me if this patch needs any polishing. I really don't know >>> why this patch still not get merged after such a long time(and 2x >>> resend), especially it already got a Reviewed-by and is a bugfix. >> >> Hi Shengyu, >> >> sorry it took such a long time for me to take a look at this patch. >> I don't see how it can even work properly in its current form, because >> of at least one bug: >> >> When switching from non-wds to wds mode, the code calls >> mt7915_mac_sta_add in order to create the new sta. However, after >> changes that I made a while back, this function does not actually upload >> the station to the MCU anymore, since it is called on the NOTEXIST->NONE >> transition before assoc. Without corresponding ASSOC/AUTHORIZE events >> (handled by mt7915_mac_sta_event), the firmware doesn't get any data for >> the new wcid. >> >> That said, I finally got around to starting to rework your patch myself. >> I will let you know when I have something ready for testing, hopefully >> later today. > > Here's my first draft: > > --- > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/ > wireless/mediatek/mt76/mt76.h > index 14927a92f9d1..f1d1b0ebd074 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76.h > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h > @@ -28,6 +28,9 @@ > > #define MT76_TOKEN_FREE_THR 64 > > +#define MT76_WED_WDS_MIN 256 > +#define MT76_WED_WDS_MAX 272 > + > #define MT_QFLAG_WED_RING GENMASK(1, 0) > #define MT_QFLAG_WED_TYPE GENMASK(4, 2) > #define MT_QFLAG_WED BIT(5) > @@ -1181,6 +1184,7 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); > int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct > ieee80211_vif *vif, > struct net_device *netdev, enum tc_setup_type type, > void *type_data); > + > #ifdef CONFIG_NET_MEDIATEK_SOC_WED > u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); > int mt76_wed_offload_enable(struct mtk_wed_device *wed); > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/ > drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c > index b287b7d9394e..ec2287459587 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c > @@ -1385,7 +1385,7 @@ static ssize_t mt7915_sta_fixed_rate_set(struct > file *file, > > out: > vif = container_of((void *)msta->vif, struct ieee80211_vif, > drv_priv); > - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, field); > + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, > &phy, field); > if (ret) > return -EFAULT; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/ > net/wireless/mediatek/mt76/mt7915/mac.c > index 9400e4af2a04..e3e65848a17f 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c > @@ -1991,7 +1991,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) > if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | > IEEE80211_RC_NSS_CHANGED | > IEEE80211_RC_BW_CHANGED)) > - mt7915_mcu_add_rate_ctrl(dev, vif, sta, true); > + mt7915_mcu_add_rate_ctrl(dev, vif, sta, &msta->wcid, true); > > if (changed & IEEE80211_RC_SMPS_CHANGED) > mt7915_mcu_add_smps(dev, vif, sta); > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/ > net/wireless/mediatek/mt76/mt7915/main.c > index fe0639c14bf9..0227ea8665f1 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c > @@ -747,7 +747,13 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, > struct ieee80211_vif *vif, > bool ext_phy = mvif->phy != &dev->phy; > int idx; > > - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); > + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && > + !is_mt7915(&dev->mt76) && > + test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) > + idx = __mt76_wcid_alloc(mdev->wcid_mask, MT76_WED_WDS_MIN, > + MT76_WED_WDS_MAX); > + else > + idx = mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA); > if (idx < 0) > return -ENOSPC; > > @@ -836,7 +842,7 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, > struct ieee80211_vif *vif, > addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30); > mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0); > > - ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); > + ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, &msta->wcid, false); > if (ret) > return ret; > > @@ -1267,6 +1273,40 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, > struct ieee80211_vif *vif, > return 0; > } > > +static void mt7915_sta_wed_set_4addr(struct mt7915_dev *dev, struct > ieee80211_vif *vif, > + struct ieee80211_sta *sta) > +{ > + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > + int min = MT76_WED_WDS_MIN, max = MT76_WED_WDS_MAX; > + int idx, prev_idx = msta->wcid.idx; > + struct mt76_wcid wcid = msta->wcid; > + int state; > + > + if (!is_mt7915(&dev->mt76)) > + return; > + > + if (msta->wcid.idx >= min && msta->wcid.idx < max) > + return; > + > + idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, min, max); > + if (idx < 0) > + return; > + > + wcid.idx = idx; > + state = msta->wcid.sta ? CONN_STATE_PORT_SECURE : > CONN_STATE_DISCONNECT; > + __mt7915_mcu_add_sta(dev, vif, sta, &wcid, state, true); > + mt7915_mcu_add_rate_ctrl(dev, vif, sta, &wcid, false); > + rcu_assign_pointer(dev->mt76.wcid[idx], &msta->wcid); > + msta->wcid.idx = idx; > + > + synchronize_rcu(); > + > + rcu_assign_pointer(dev->mt76.wcid[prev_idx], NULL); > + mt76_wcid_mask_clear(dev->mt76.wcid_mask, prev_idx); > + wcid.idx = prev_idx; > + __mt7915_mcu_add_sta(dev, vif, sta, &wcid, CONN_STATE_DISCONNECT, > false); > +} > + > static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > struct ieee80211_vif *vif, > struct ieee80211_sta *sta, > @@ -1280,6 +1320,9 @@ static void mt7915_sta_set_4addr(struct > ieee80211_hw *hw, > else > clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); > > + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && enabled) > + mt7915_sta_wed_set_4addr(dev, vif, sta); > + > if (!msta->wcid.sta) > return; > > @@ -1729,15 +1772,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw > *hw, > if (!mtk_wed_device_active(wed)) > return -ENODEV; > > - if (msta->wcid.idx > 0xff) > + if (msta->wcid.idx > MT7915_WTBL_STA) > return -EIO; > > path->type = DEV_PATH_MTK_WDMA; > path->dev = ctx->dev; > path->mtk_wdma.wdma_idx = wed->wdma_idx; > path->mtk_wdma.bss = mvif->mt76.idx; > - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; > path->mtk_wdma.queue = phy != &dev->phy; > + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || > + is_mt7915(&dev->mt76)) > + path->mtk_wdma.wcid = msta->wcid.idx; > + else > + path->mtk_wdma.wcid = 0x3ff; > > ctx->dev = NULL; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/ > net/wireless/mediatek/mt76/mt7915/mcu.c > index cf948628e588..26497b580eb6 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > @@ -1359,6 +1359,7 @@ mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode > smps) > int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > struct ieee80211_sta *sta, > + struct mt76_wcid *wcid, > void *data, u32 field) > { > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > @@ -1430,7 +1431,7 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > if (ret) > return ret; > > - return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, NULL, > + return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, > NULL, > RATE_PARAM_MMPS_UPDATE); > } > > @@ -1439,17 +1440,19 @@ mt7915_mcu_set_spe_idx(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > struct ieee80211_sta *sta) > { > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > struct mt76_phy *mphy = mvif->phy->mt76; > u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask); > > - return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &spe_idx, > - RATE_PARAM_SPE_UPDATE); > + return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &msta->wcid, > + &spe_idx, RATE_PARAM_SPE_UPDATE); > } > > static int > mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > - struct ieee80211_sta *sta) > + struct ieee80211_sta *sta, > + struct mt76_wcid *wcid) > { > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; > @@ -1497,7 +1500,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev > *dev, > > /* fixed single rate */ > if (nrates == 1) { > - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, > + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, > RATE_PARAM_FIXED_MCS); > if (ret) > return ret; > @@ -1519,7 +1522,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev > *dev, > else > mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); > > - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, > + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, > RATE_PARAM_FIXED_GI); > if (ret) > return ret; > @@ -1527,7 +1530,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev > *dev, > > /* fixed HE_LTF */ > if (mask->control[band].he_ltf != GENMASK(7, 0)) { > - ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, > + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, wcid, &phy, > RATE_PARAM_FIXED_HE_LTF); > if (ret) > return ret; > @@ -1640,15 +1643,14 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff > *skb, struct mt7915_dev *dev, > } > > int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct > ieee80211_vif *vif, > - struct ieee80211_sta *sta, bool changed) > + struct ieee80211_sta *sta, struct mt76_wcid *wcid, > + bool changed) > { > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; > struct sk_buff *skb; > int ret; > > - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, > - &msta->wcid); > + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, wcid); > if (IS_ERR(skb)) > return PTR_ERR(skb); > > @@ -1673,7 +1675,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev > *dev, struct ieee80211_vif *vif, > * and updates as peer fixed rate parameters, which overrides > * sta_rec_ra and firmware rate control algorithm. > */ > - return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta); > + return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta, wcid); > } > > static int > @@ -1704,8 +1706,9 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > sizeof(req), true); > } > > -int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, > - struct ieee80211_sta *sta, int conn_state, bool newly) > +int __mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif > *vif, > + struct ieee80211_sta *sta, struct mt76_wcid *wcid, > + int conn_state, bool newly) > { > struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; > struct ieee80211_link_sta *link_sta; > @@ -1715,9 +1718,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > > msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; > link_sta = sta ? &sta->deflink : NULL; > + if (!wcid) > + wcid = &msta->wcid; > > - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, > - &msta->wcid); > + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, wcid); > if (IS_ERR(skb)) > return PTR_ERR(skb); > > @@ -2413,10 +2417,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev > *dev) > > mt76_connac_mcu_del_wtbl_all(&dev->mt76); > > - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && > - is_mt7915(&dev->mt76)) || > - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); > +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) > + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { > + if (is_mt7915(&dev->mt76) || > + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), > + 0, 0, 0); > + else > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), > + MCU_WA_PARAM_WED_VERSION, > + dev->mt76.mmio.wed.rev_id, 0); > + if (ret) > + return ret; > + } > +#endif > > ret = mt7915_mcu_set_mwds(dev, 1); > if (ret) > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/ > net/wireless/mediatek/mt76/mt7915/mcu.h > index 086ad89ecd91..989f24cb49eb 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > @@ -278,6 +278,7 @@ enum { > MCU_WA_PARAM_PDMA_RX = 0x04, > MCU_WA_PARAM_CPU_UTIL = 0x0b, > MCU_WA_PARAM_RED = 0x0e, > + MCU_WA_PARAM_WED_VERSION = 0x32, > MCU_WA_PARAM_RED_SETTING = 0x40, > }; > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/ > drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h > index 2e94347c46d6..c781058a416f 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h > @@ -455,8 +455,16 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, > struct ieee80211_vif *vif, bool enable); > int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, > struct ieee80211_vif *vif, int enable); > -int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, > - struct ieee80211_sta *sta, int conn_state, bool newly); > +int __mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif > *vif, > + struct ieee80211_sta *sta, struct mt76_wcid *wcid, > + int conn_state, bool newly); > +static inline int > +mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, > + struct ieee80211_sta *sta, int conn_state, bool newly) > +{ > + return __mt7915_mcu_add_sta(dev, vif, sta, NULL, conn_state, newly); > +} > + > int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, > struct ieee80211_ampdu_params *params, > bool add); > @@ -472,7 +480,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, > struct ieee80211_vif *vif, > int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct > ieee80211_vif *vif, > struct ieee80211_he_obss_pd *he_obss_pd); > int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct > ieee80211_vif *vif, > - struct ieee80211_sta *sta, bool changed); > + struct ieee80211_sta *sta, struct mt76_wcid *wcid, > + bool changed); > int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif > *vif, > struct ieee80211_sta *sta); > int mt7915_set_channel(struct mt76_phy *mphy); > @@ -482,6 +491,7 @@ int mt7915_mcu_update_edca(struct mt7915_dev *dev, > void *req); > int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, > struct ieee80211_vif *vif, > struct ieee80211_sta *sta, > + struct mt76_wcid *wcid, > void *data, u32 field); > int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); > int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 > *read_buf); > diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/ > wireless/mediatek/mt76/util.c > index 95b3dc96e4c4..9fa60d380ede 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.c > +++ b/drivers/net/wireless/mediatek/mt76/util.c > @@ -42,12 +42,19 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 > offset, u32 mask, u32 val, > } > EXPORT_SYMBOL_GPL(____mt76_poll_msec); > > -int mt76_wcid_alloc(u32 *mask, int size) > +int __mt76_wcid_alloc(u32 *mask, int min, int size) > { > + u32 min_mask = ~0; > int i, idx = 0, cur; > > + mask += min / 32; > + min %= 32; > + if (min > 0) > + min_mask = ~((1 << min) - 1); > + > for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { > - idx = ffs(~mask[i]); > + idx = ffs(~mask[i] & min_mask); > + min_mask = ~0; > if (!idx) > continue; > > @@ -62,7 +69,7 @@ int mt76_wcid_alloc(u32 *mask, int size) > > return -1; > } > -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); > +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); > > int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) > { > diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/ > wireless/mediatek/mt76/util.h > index 260965dde94c..bca2893f980e 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.h > +++ b/drivers/net/wireless/mediatek/mt76/util.h > @@ -27,7 +27,12 @@ enum { > #define MT76_INCR(_var, _size) \ > (_var = (((_var) + 1) % (_size))) > > -int mt76_wcid_alloc(u32 *mask, int size); > +int __mt76_wcid_alloc(u32 *mask, int min, int size); > + > +static inline int mt76_wcid_alloc(u32 *mask, int size) > +{ > + return __mt76_wcid_alloc(mask, 0, size); > +} > > static inline void > mt76_wcid_mask_set(u32 *mask, int idx) [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 6977 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 840 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled @ 2025-04-12 9:49 Shengyu Qu 0 siblings, 0 replies; 8+ messages in thread From: Shengyu Qu @ 2025-04-12 9:49 UTC (permalink / raw) To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg, angelogioacchino.delregno, johannes.berg, miriam.rachel.korenblit, nicolas.cavallari, christophe.jaillet, benjamin-jw.lin, StanleyYP.Wang, quic_adisi, deren.wu, chui-hao.chiu, bo.jiao, gustavoars, razvan.grigore, linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek Cc: Shengyu Qu, Ping-Ke Shih, Sujuan Chen The current WED only supports 256 wcid, whereas mt7986 can support up to 512 entries, so firmware provides a rule to get sta_info by DA when wcid is set to 0x3ff by txd. Also, WED provides a register to overwrite txd wcid, that is, wcid[9:8] can be overwritten by 0x3 and wcid[7:0] is set to 0xff by host driver. However, firmware is unable to get sta_info from DA as DA != RA for 4addr cases, so firmware and wifi host driver both use wcid (256 - 271) and (768 ~ 783) for sync up to get correct sta_info. Currently WDS+WED config is completely broken on MT7986/7981 devices if without this patch. Reviewed-by: Ping-Ke Shih <pkshih@realtek.com> Tested-by: Sujuan Chen <sujuan.chen@mediatek.com> Co-developed-by: Bo Jiao <bo.jiao@mediatek.com> Signed-off-by: Bo Jiao <bo.jiao@mediatek.com> Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> Signed-off-by: Shengyu Qu <wiagn233@outlook.com> --- Changes since v1: - Drop duplicate setting in mmio - Reduce the patch size by redefining mt76_wcid_alloc Changes since v2: - Rework wds wcid getting flow Changes since v3: - Rebase to next-20240703 - Sync with downstream patch Changes since v4: - Rebase to next-20240802 Changes since v5: - Fixed build test error reported by robot - Rebase to next-20240805 Changes since v6: - Fix potential race conditions on tx/rx packets during the transition - Rebase to Felix's newest codebase Changes since v7: - Fix build fail Changes since v8: - Changed code as Shih advised Changes since v9: - Changed code as Shih advised - Moved mt76_wcid_alloc to mt76.h --- drivers/net/wireless/mediatek/mt76/mt76.h | 15 ++++++ .../net/wireless/mediatek/mt76/mt7915/main.c | 53 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++-- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 + drivers/net/wireless/mediatek/mt76/util.c | 37 +++++++++++-- drivers/net/wireless/mediatek/mt76/util.h | 2 +- 6 files changed, 115 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index d7cd467b812f..7f590854959e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -28,6 +28,9 @@ #define MT76_TOKEN_FREE_THR 64 +#define MT76_WED_WDS_MIN 256 +#define MT76_WED_WDS_MAX 272 + #define MT_QFLAG_WED_RING GENMASK(1, 0) #define MT_QFLAG_WED_TYPE GENMASK(4, 2) #define MT_QFLAG_WED BIT(5) @@ -73,6 +76,12 @@ enum mt76_wed_type { MT76_WED_RRO_Q_IND, }; +enum mt76_wed_state { + MT76_WED_DEFAULT, + MT76_WED_ACTIVE, + MT76_WED_WDS_ACTIVE, +}; + struct mt76_bus_ops { u32 (*rr)(struct mt76_dev *dev, u32 offset); void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); @@ -1169,6 +1178,12 @@ void mt76_wed_dma_reset(struct mt76_dev *dev); int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct net_device *netdev, enum tc_setup_type type, void *type_data); + +static inline int mt76_wcid_alloc(u32 *mask, int size) +{ + return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); +} + #ifdef CONFIG_NET_MEDIATEK_SOC_WED u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); int mt76_wed_offload_enable(struct mtk_wed_device *wed); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 3aa31c5cefa6..fcbf4f971026 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -744,9 +744,16 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; bool ext_phy = mvif->phy != &dev->phy; + u8 flags = MT76_WED_DEFAULT; int idx; - 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; @@ -1271,6 +1278,11 @@ 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; + struct ieee80211_sta *pre_sta; + struct mt7915_sta *pre_msta; + u8 flags = MT76_WED_DEFAULT; + int tmp_idx; if (enabled) set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); @@ -1280,6 +1292,37 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, 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 = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); + if (!pre_sta) + goto error_alloc; + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; + + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; + + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); + if (tmp_idx < 0) + goto error_wcid; + pre_msta->wcid.idx = (u16)tmp_idx; + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); + + tmp_idx = msta->wcid.idx; + msta->wcid.idx = pre_msta->wcid.idx; + pre_msta->wcid.idx = (u16)tmp_idx; + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); + + synchronize_rcu(); + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); + +error_wcid: + kfree(pre_sta); + } + +error_alloc: mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } @@ -1726,15 +1769,19 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, if (!mtk_wed_device_active(wed)) return -ENODEV; - if (msta->wcid.idx > 0xff) + if (msta->wcid.idx > MT7915_WTBL_STA) return -EIO; path->type = DEV_PATH_MTK_WDMA; path->dev = ctx->dev; path->mtk_wdma.wdma_idx = wed->wdma_idx; path->mtk_wdma.bss = mvif->mt76.idx; - path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; path->mtk_wdma.queue = phy != &dev->phy; + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || + is_mt7915(&dev->mt76)) + path->mtk_wdma.wcid = msta->wcid.idx; + else + path->mtk_wdma.wcid = 0x3ff; ctx->dev = NULL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 427542777abc..61a854d2c416 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2403,10 +2403,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) mt76_connac_mcu_del_wtbl_all(&dev->mt76); - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && - is_mt7915(&dev->mt76)) || - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + if (is_mt7915(&dev->mt76) || + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), + 0, 0, 0); + else + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), + MCU_WA_PARAM_WED_VERSION, + dev->mt76.mmio.wed.rev_id, 0); + if (ret) + return ret; + } +#endif ret = mt7915_mcu_set_mwds(dev, 1); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 086ad89ecd91..989f24cb49eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -278,6 +278,7 @@ enum { MCU_WA_PARAM_PDMA_RX = 0x04, MCU_WA_PARAM_CPU_UTIL = 0x0b, MCU_WA_PARAM_RED = 0x0e, + MCU_WA_PARAM_WED_VERSION = 0x32, MCU_WA_PARAM_RED_SETTING = 0x40, }; diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 95b3dc96e4c4..e80bef2b33a1 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -42,8 +42,10 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, } EXPORT_SYMBOL_GPL(____mt76_poll_msec); -int mt76_wcid_alloc(u32 *mask, int size) +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) { + int max = MT76_WED_WDS_MAX; + int min = MT76_WED_WDS_MIN; int i, idx = 0, cur; for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) idx--; cur = i * 32 + idx; - if (cur >= size) + + switch (flag) { + case MT76_WED_ACTIVE: + if (cur >= min && cur < max) + continue; + + if (cur >= size) { + u32 end = max - min - 1; + + i = min / 32; + idx = ffs(~mask[i] & GENMASK(end, 0)); + if (!idx) + goto error; + idx--; + cur = min + idx; + } + break; + case MT76_WED_WDS_ACTIVE: + if (cur < min) + continue; + if (cur >= max) + goto error; + + break; + default: + if (cur >= size) + goto error; + break; + } mask[i] |= BIT(idx); return cur; } +error: return -1; } -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) { diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index 260965dde94c..fe95a847182e 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -27,7 +27,7 @@ enum { #define MT76_INCR(_var, _size) \ (_var = (((_var) + 1) % (_size))) -int mt76_wcid_alloc(u32 *mask, int size); +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); static inline void mt76_wcid_mask_set(u32 *mask, int idx) -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-06-25 17:25 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-21 14:04 [PATCH v10 RESEND] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu 2025-05-18 14:41 ` Shengyu Qu 2025-05-25 13:42 ` Shengyu Qu 2025-06-24 14:11 ` Shengyu Qu 2025-06-25 10:18 ` Felix Fietkau 2025-06-25 11:00 ` Felix Fietkau 2025-06-25 17:25 ` Shengyu Qu -- strict thread matches above, loose matches on Subject: below -- 2025-04-12 9:49 Shengyu Qu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).