* [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
@ 2024-08-05 12:43 Shengyu Qu
2024-08-14 18:55 ` Shengyu Qu
2024-09-05 12:31 ` Felix Fietkau
0 siblings, 2 replies; 7+ messages in thread
From: Shengyu Qu @ 2024-08-05 12:43 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: Shengyu Qu, 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.
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
---
drivers/net/wireless/mediatek/mt76/mt76.h | 9 +++++
.../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++++++++++++++--
.../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 | 7 +++-
6 files changed, 93 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 4a58a78d5ed25..1186a4998faff 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)
@@ -71,6 +74,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);
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;
@@ -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);
}
@@ -1644,15 +1666,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 2185cd24e2e1c..e74709e4f836d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -2352,10 +2352,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
if (ret)
return ret;
- 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);
+#ifdef 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 b41ac4aaced7f..b2bf5472b2d70 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -279,6 +279,7 @@ enum {
MCU_WA_PARAM_CPU_UTIL = 0x0b,
MCU_WA_PARAM_RED = 0x0e,
MCU_WA_PARAM_RED_SETTING = 0x40,
+ MCU_WA_PARAM_WED_VERSION = 0x32,
};
enum mcu_mmps_mode {
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index d6c01a2dd1988..461b74068fc30 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,9 +42,11 @@ 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 i, idx = 0, cur;
+ int min = MT76_WED_WDS_MIN;
+ int max = MT76_WED_WDS_MAX;
for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
idx = ffs(~mask[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, bool ext_phy)
{
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 260965dde94cf..99b7263c0a205 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 size, u8 flags);
+
+static inline int mt76_wcid_alloc(u32 *mask, int size)
+{
+ return __mt76_wcid_alloc(mask, size, 0);
+}
static inline void
mt76_wcid_mask_set(u32 *mask, int idx)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-08-05 12:43 [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu
@ 2024-08-14 18:55 ` Shengyu Qu
2024-09-05 12:31 ` Felix Fietkau
1 sibling, 0 replies; 7+ messages in thread
From: Shengyu Qu @ 2024-08-14 18:55 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: wiagn233, Bo Jiao
[-- Attachment #1.1.1: Type: text/plain, Size: 9354 bytes --]
Hello everyone,
Could anyone give this patch a review?
Best regards,
Shengyu
在 2024/8/5 20:43, 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.
>
> 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
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 9 +++++
> .../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++++++++++++++--
> .../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 | 7 +++-
> 6 files changed, 93 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 4a58a78d5ed25..1186a4998faff 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)
> @@ -71,6 +74,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);
> 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;
>
> @@ -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);
> }
>
> @@ -1644,15 +1666,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 2185cd24e2e1c..e74709e4f836d 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> @@ -2352,10 +2352,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
> if (ret)
> return ret;
>
> - 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);
> +#ifdef 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 b41ac4aaced7f..b2bf5472b2d70 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> @@ -279,6 +279,7 @@ enum {
> MCU_WA_PARAM_CPU_UTIL = 0x0b,
> MCU_WA_PARAM_RED = 0x0e,
> MCU_WA_PARAM_RED_SETTING = 0x40,
> + MCU_WA_PARAM_WED_VERSION = 0x32,
> };
>
> enum mcu_mmps_mode {
> diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
> index d6c01a2dd1988..461b74068fc30 100644
> --- a/drivers/net/wireless/mediatek/mt76/util.c
> +++ b/drivers/net/wireless/mediatek/mt76/util.c
> @@ -42,9 +42,11 @@ 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 i, idx = 0, cur;
> + int min = MT76_WED_WDS_MIN;
> + int max = MT76_WED_WDS_MAX;
>
> for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
> idx = ffs(~mask[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, bool ext_phy)
> {
> diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
> index 260965dde94cf..99b7263c0a205 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 size, u8 flags);
> +
> +static inline int mt76_wcid_alloc(u32 *mask, int size)
> +{
> + return __mt76_wcid_alloc(mask, size, 0);
> +}
>
> 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] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-08-05 12:43 [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu
2024-08-14 18:55 ` Shengyu Qu
@ 2024-09-05 12:31 ` Felix Fietkau
2024-09-05 17:10 ` Shengyu Qu
2024-09-08 16:27 ` Shengyu Qu
1 sibling, 2 replies; 7+ messages in thread
From: Felix Fietkau @ 2024-09-05 12:31 UTC (permalink / raw)
To: Shengyu Qu, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: Bo Jiao
On 05.08.24 14:43, Shengyu Qu wrote:
> 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.
>
> 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
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 9 +++++
> .../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++++++++++++++--
> .../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 | 7 +++-
> 6 files changed, 93 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 4a58a78d5ed25..1186a4998faff 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)
> @@ -71,6 +74,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);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> index 049223df9beb1..dc4d87e004a0f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> @@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> bool ext_phy = mvif->phy != &dev->phy;
> int ret, idx;
> u32 addr;
> + u8 flags = MT76_WED_DEFAULT;
>
> - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
> + if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> + !is_mt7915(&dev->mt76)) {
> + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
> + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
> + }
> +
> + idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
> if (idx < 0)
> return -ENOSPC;
>
I'd prefer to replace the mt76_wcid_alloc flags argument with an
explicit start offset argument.
> @@ -1201,12 +1208,27 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
> {
> 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
This should allow mgmt tx/rx to work while the sta is being migrated to
the new wcid entry.
- Felix
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-09-05 12:31 ` Felix Fietkau
@ 2024-09-05 17:10 ` Shengyu Qu
2024-09-05 17:23 ` Felix Fietkau
2024-09-08 16:27 ` Shengyu Qu
1 sibling, 1 reply; 7+ messages in thread
From: Shengyu Qu @ 2024-09-05 17:10 UTC (permalink / raw)
To: Felix Fietkau, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: wiagn233, Bo Jiao
[-- Attachment #1.1.1: Type: text/plain, Size: 6270 bytes --]
Hello Felix,
Which git repo should I base on? Is this one?
https://github.com/nbd168/wireless
Or use wireless-next repo at git.kernel.org?
Best regards,
Shengyu
在 2024/9/5 20:31, Felix Fietkau 写道:
> On 05.08.24 14:43, Shengyu Qu wrote:
>> 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.
>>
>> 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
>> ---
>> drivers/net/wireless/mediatek/mt76/mt76.h | 9 +++++
>> .../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++++++++++++++--
>> .../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 | 7 +++-
>> 6 files changed, 93 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h
>> b/drivers/net/wireless/mediatek/mt76/mt76.h
>> index 4a58a78d5ed25..1186a4998faff 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)
>> @@ -71,6 +74,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);
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> index 049223df9beb1..dc4d87e004a0f 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
>> @@ -745,8 +745,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev,
>> struct ieee80211_vif *vif,
>> bool ext_phy = mvif->phy != &dev->phy;
>> int ret, idx;
>> u32 addr;
>> + u8 flags = MT76_WED_DEFAULT;
>> - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
>> + if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
>> + !is_mt7915(&dev->mt76)) {
>> + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ?
>> + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE;
>> + }
>> +
>> + idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags);
>> if (idx < 0)
>> return -ENOSPC;
>
> I'd prefer to replace the mt76_wcid_alloc flags argument with an
> explicit start offset argument.
>
>> @@ -1201,12 +1208,27 @@ static void mt7915_sta_set_4addr(struct
>> ieee80211_hw *hw,
>> {
>> 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
>
> This should allow mgmt tx/rx to work while the sta is being migrated to
> the new wcid entry.
>
> - Felix
[-- 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] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-09-05 17:10 ` Shengyu Qu
@ 2024-09-05 17:23 ` Felix Fietkau
0 siblings, 0 replies; 7+ messages in thread
From: Felix Fietkau @ 2024-09-05 17:23 UTC (permalink / raw)
To: Shengyu Qu, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: Bo Jiao
On 05.09.24 19:10, Shengyu Qu wrote:
> Hello Felix,
>
> Which git repo should I base on? Is this one?
> https://github.com/nbd168/wireless
> Or use wireless-next repo at git.kernel.org?
Please use my github tree.
Thanks,
- Felix
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-09-05 12:31 ` Felix Fietkau
2024-09-05 17:10 ` Shengyu Qu
@ 2024-09-08 16:27 ` Shengyu Qu
2024-12-02 8:49 ` Qu Shengyu
1 sibling, 1 reply; 7+ messages in thread
From: Shengyu Qu @ 2024-09-08 16:27 UTC (permalink / raw)
To: Felix Fietkau, lorenzo, ryder.lee, shayne.chen, sean.wang, kvalo,
matthias.bgg, angelogioacchino.delregno, daniel,
miriam.rachel.korenblit, money.wang, StanleyYP.Wang, meichia.chiu,
chui-hao.chiu, johannes.berg, quic_adisi, sujuan.chen, allen.ye,
linux-wireless, linux-kernel, linux-arm-kernel
Cc: wiagn233, Bo Jiao
[-- Attachment #1.1.1: Type: text/plain, Size: 5204 bytes --]
>> 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
[-- 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] 7+ messages in thread
* Re: [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled
2024-09-08 16:27 ` Shengyu Qu
@ 2024-12-02 8:49 ` Qu Shengyu
0 siblings, 0 replies; 7+ messages in thread
From: Qu Shengyu @ 2024-12-02 8:49 UTC (permalink / raw)
To: Felix Fietkau, lorenzo@kernel.org, ryder.lee@mediatek.com,
shayne.chen@mediatek.com, sean.wang@mediatek.com,
kvalo@kernel.org, matthias.bgg@gmail.com,
angelogioacchino.delregno@collabora.com, daniel@makrotopia.org,
miriam.rachel.korenblit@intel.com, money.wang@mediatek.com,
StanleyYP.Wang@mediatek.com, meichia.chiu@mediatek.com,
chui-hao.chiu@mediatek.com, johannes.berg@intel.com,
quic_adisi@quicinc.com, sujuan.chen@mediatek.com,
allen.ye@mediatek.com, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Cc: Bo Jiao, Qu Shengyu
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@outlook.com> 写道:
>
>
>>
>>> 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>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-12-02 8:50 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-05 12:43 [PATCH v6] wifi: mt76: mt7915: add wds support when wed is enabled Shengyu Qu
2024-08-14 18:55 ` Shengyu Qu
2024-09-05 12:31 ` Felix Fietkau
2024-09-05 17:10 ` Shengyu Qu
2024-09-05 17:23 ` Felix Fietkau
2024-09-08 16:27 ` Shengyu Qu
2024-12-02 8:49 ` Qu Shengyu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox