Skip to content

Commit

Permalink
wifi: mt76: mt7915: add wds support when wed is enabled
Browse files Browse the repository at this point in the history
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

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>
  • Loading branch information
Sujuan Chen authored and intel-lab-lkp committed Dec 20, 2022
1 parent 117dbed commit 91549c1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 9 deletions.
9 changes: 9 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt76.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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(3, 2)
#define MT_QFLAG_WED BIT(4)
Expand Down Expand Up @@ -60,6 +63,12 @@ enum mt76_wed_type {
MT76_WED_Q_RX,
};

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);
Expand Down
32 changes: 29 additions & 3 deletions drivers/net/wireless/mediatek/mt76/mt7915/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,8 +664,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
bool ext_phy = mvif->phy != &dev->phy;
int ret, idx;
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;

Expand Down Expand Up @@ -1115,12 +1122,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);
}

Expand Down Expand Up @@ -1485,15 +1507,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;

Expand Down
13 changes: 11 additions & 2 deletions drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2310,8 +2310,17 @@ 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))
mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
if (is_mt7915(&dev->mt76))
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;
}

ret = mt7915_mcu_set_mwds(dev, 1);
if (ret)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

enum mcu_mmps_mode {
Expand Down
37 changes: 34 additions & 3 deletions drivers/net/wireless/mediatek/mt76/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand All @@ -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)
{
Expand Down
7 changes: 6 additions & 1 deletion drivers/net/wireless/mediatek/mt76/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 91549c1

Please sign in to comment.