[Add kernel flowblock support and sync Wifi]
[Description]
Add kernel flowblock support and sync Wifi
[Release-log]
N/A
diff --git a/recipes-kernel/linux-mt76/files/patches/1111-mt76-testmode-additional-supports.patch b/recipes-kernel/linux-mt76/files/patches/1111-mt76-testmode-additional-supports.patch
index 292e2fc..d39e83d 100644
--- a/recipes-kernel/linux-mt76/files/patches/1111-mt76-testmode-additional-supports.patch
+++ b/recipes-kernel/linux-mt76/files/patches/1111-mt76-testmode-additional-supports.patch
@@ -1,7 +1,7 @@
-From de93c29a69f28d2cf9d2e10fbd3cb1ebda771548 Mon Sep 17 00:00:00 2001
+From 9c76671cd831d28e5b270baa23c71dfc4aaf8410 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 21 Apr 2022 15:43:19 +0800
-Subject: [PATCH 1111/1115] mt76: testmode: additional supports
+Subject: [PATCH] mt76: testmode: additional supports
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
@@ -20,14 +20,14 @@
mt7915/regs.h | 3 +
mt7915/testmode.c | 1171 ++++++++++++++++++++++++++++++++++++++++++---
mt7915/testmode.h | 278 +++++++++++
- testmode.c | 274 +++++++++--
+ testmode.c | 275 +++++++++--
testmode.h | 75 +++
tools/fields.c | 80 ++++
tx.c | 3 +-
- 19 files changed, 1962 insertions(+), 149 deletions(-)
+ 19 files changed, 1963 insertions(+), 149 deletions(-)
diff --git a/dma.c b/dma.c
-index 30de8be..f6f5f12 100644
+index f22273cd..03ee9109 100644
--- a/dma.c
+++ b/dma.c
@@ -426,8 +426,7 @@ free:
@@ -41,7 +41,7 @@
#endif
diff --git a/mac80211.c b/mac80211.c
-index c1df063..dc3c63e 100644
+index a7e082f7..9984def5 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -55,6 +55,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
@@ -71,7 +71,7 @@
static const struct ieee80211_channel mt76_channels_6ghz[] = {
diff --git a/mt76.h b/mt76.h
-index 28720ee..062c5ce 100644
+index 8325409a..4c8a671f 100644
--- a/mt76.h
+++ b/mt76.h
@@ -602,6 +602,21 @@ struct mt76_testmode_ops {
@@ -235,7 +235,7 @@
static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
{
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 261181d..cd35068 100644
+index 261181dc..cd350689 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -391,6 +391,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
@@ -257,7 +257,7 @@
return;
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 32e540c..a0e6fa6 100644
+index 32e540cc..a0e6fa6e 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -967,6 +967,7 @@ enum {
@@ -277,7 +277,7 @@
MCU_EXT_CMD_CSI_CTRL = 0xc2,
};
diff --git a/mt7915/init.c b/mt7915/init.c
-index 0d5109a..b549fa0 100644
+index 0d5109a3..b549fa04 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
@@ -576,7 +576,7 @@ static void mt7915_init_work(struct work_struct *work)
@@ -290,7 +290,7 @@
mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 0593270..8fd4618 100644
+index f13456bf..5e5df23d 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -565,17 +565,39 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -356,7 +356,7 @@
}
diff --git a/mt7915/main.c b/mt7915/main.c
-index dc5e4b0..e4b2076 100644
+index dc5e4b0f..e4b20766 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -224,7 +224,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
@@ -369,7 +369,7 @@
mvif->mt76.wmm_idx += 2;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index aee3a8c..810d72e 100644
+index fa8f51da..41a8e7e2 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -434,6 +434,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -392,7 +392,7 @@
!rxd->seq)
mt7915_mcu_rx_unsolicited_event(dev, skb);
else
-@@ -2812,14 +2818,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
+@@ -2809,14 +2815,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
return 0;
}
@@ -410,7 +410,7 @@
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 75442ba..873a805 100644
+index 15b74732..1b147421 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -8,10 +8,15 @@
@@ -442,7 +442,7 @@
MT_BF_TYPE_UPDATE = 20,
MT_BF_MODULE_UPDATE = 25
};
-@@ -661,10 +672,19 @@ struct mt7915_muru {
+@@ -664,10 +675,19 @@ struct mt7915_muru {
#define MURU_OFDMA_SCH_TYPE_UL BIT(1)
/* Common Config */
@@ -467,7 +467,7 @@
enum {
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index bccb108..a84970d 100644
+index 6e140e2d..6d1dbdbd 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -76,6 +76,7 @@ static const u32 mt7915_offs[] = {
@@ -487,7 +487,7 @@
[AGG_PCR0] = 0x040,
[AGG_ACR0] = 0x054,
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 9f5da64..ff92e55 100644
+index 07a1c9ce..7c7d6bd3 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -303,6 +303,9 @@ struct mt7915_phy {
@@ -533,7 +533,7 @@
static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
{
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index 47bae86..444440e 100644
+index 47bae86e..444440e1 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -51,6 +51,7 @@ enum offs_rev {
@@ -554,7 +554,7 @@
(_n) * 4))
#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 123ceaf..a0a9f7b 100644
+index 123ceaf9..a0a9f7be 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -9,6 +9,9 @@
@@ -1887,7 +1887,7 @@
+ .set_eeprom = mt7915_tm_set_eeprom,
};
diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index a1c54c8..01b08e9 100644
+index a1c54c89..01b08e9e 100644
--- a/mt7915/testmode.h
+++ b/mt7915/testmode.h
@@ -4,6 +4,8 @@
@@ -2202,17 +2202,18 @@
+
#endif
diff --git a/testmode.c b/testmode.c
-index e6d1f70..2c699ac 100644
+index 4a24f6c9..690e9a7d 100644
--- a/testmode.c
+++ b/testmode.c
-@@ -25,28 +25,15 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+@@ -25,28 +25,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
};
EXPORT_SYMBOL_GPL(mt76_tm_policy);
-void mt76_testmode_tx_pending(struct mt76_phy *phy)
+static void
+mt76_testmode_queue_tx(struct mt76_phy *phy, struct mt76_wcid *wcid,
-+ struct sk_buff *skb, struct mt76_queue *q, u16 limit)
++ struct sk_buff *skb, struct mt76_queue *q, int qid,
++ u16 limit)
{
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
@@ -2239,7 +2240,7 @@
q->queued < q->ndesc / 2) {
int ret;
-@@ -55,13 +42,65 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
+@@ -55,13 +43,65 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
if (ret < 0)
break;
@@ -2276,7 +2277,7 @@
+ q = phy->q_tx[qid];
+ spin_lock_bh(&q->lock);
+ mt76_testmode_queue_tx(phy, &phy->dev->global_wcid,
-+ td->tx_skb, q, tx_queued_limit);
++ td->tx_skb, q, qid, tx_queued_limit);
+ spin_unlock_bh(&q->lock);
+
+ return;
@@ -2293,7 +2294,7 @@
+ if (remain < tx_queued_limit)
+ tx_queued_limit = remain;
+
-+ mt76_testmode_queue_tx(phy, td->cur_entry, ed->tx_skb, q, tx_queued_limit);
++ mt76_testmode_queue_tx(phy, td->cur_entry, ed->tx_skb, q, qid, tx_queued_limit);
+
+ if (td->tx_pending % td->tx_count == 0 || is_mu)
+ td->cur_entry = list_next_entry(td->cur_entry, list);
@@ -2305,7 +2306,7 @@
}
static u32
-@@ -87,15 +126,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
+@@ -87,15 +127,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
}
static void
@@ -2341,7 +2342,7 @@
{
#define MT_TXP_MAX_LEN 4095
u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
-@@ -117,7 +172,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -117,7 +173,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
nfrags = len / MT_TXP_MAX_LEN;
head_len = nfrags ? MT_TXP_MAX_LEN : len;
@@ -2351,7 +2352,7 @@
fc |= IEEE80211_STYPE_QOS_DATA;
head = alloc_skb(head_len, GFP_KERNEL);
-@@ -126,9 +182,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -126,9 +183,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
hdr = __skb_put_zero(head, head_len);
hdr->frame_control = cpu_to_le16(fc);
@@ -2364,7 +2365,7 @@
skb_set_queue_mapping(head, IEEE80211_AC_BE);
info = IEEE80211_SKB_CB(head);
-@@ -152,7 +208,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -152,7 +209,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
frag = alloc_skb(frag_len, GFP_KERNEL);
if (!frag) {
@@ -2373,7 +2374,7 @@
dev_kfree_skb(head);
return -ENOMEM;
}
-@@ -165,15 +221,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -165,15 +222,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
frag_tail = &(*frag_tail)->next;
}
@@ -2393,7 +2394,7 @@
{
struct mt76_testmode_data *td = &phy->test;
struct ieee80211_tx_info *info;
-@@ -181,7 +236,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -181,7 +237,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
u8 max_nss = hweight8(phy->antenna_mask);
int ret;
@@ -2402,7 +2403,7 @@
if (ret)
return ret;
-@@ -191,7 +246,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -191,7 +247,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
if (td->tx_antenna_mask)
max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
@@ -2411,7 +2412,7 @@
rate = &info->control.rates[0];
rate->count = 1;
rate->idx = td->tx_rate_idx;
-@@ -263,6 +318,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -263,6 +319,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
out:
return 0;
}
@@ -2437,7 +2438,7 @@
static void
mt76_testmode_tx_start(struct mt76_phy *phy)
-@@ -273,6 +347,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
+@@ -273,6 +348,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
td->tx_queued = 0;
td->tx_done = 0;
td->tx_pending = td->tx_count;
@@ -2452,7 +2453,7 @@
mt76_worker_schedule(&dev->tx_worker);
}
-@@ -291,7 +373,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
+@@ -291,7 +374,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
MT76_TM_TIMEOUT * HZ);
@@ -2461,7 +2462,7 @@
}
static inline void
-@@ -322,6 +404,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
+@@ -322,6 +405,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
@@ -2470,7 +2471,7 @@
}
static int
-@@ -331,8 +415,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
+@@ -331,8 +416,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
struct mt76_dev *dev = phy->dev;
int err;
@@ -2484,7 +2485,7 @@
if (state == MT76_TM_STATE_TX_FRAMES) {
err = mt76_testmode_tx_init(phy);
-@@ -402,6 +490,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
+@@ -402,6 +491,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
return 0;
}
@@ -2529,7 +2530,7 @@
int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len)
{
-@@ -425,6 +551,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -425,6 +552,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&dev->mutex);
@@ -2541,7 +2542,7 @@
if (tb[MT76_TM_ATTR_RESET]) {
mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
memset(td, 0, sizeof(*td));
-@@ -452,7 +583,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -452,7 +584,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
&td->tx_duty_cycle, 0, 99) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
@@ -2553,7 +2554,7 @@
goto out;
if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -484,8 +618,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -484,8 +619,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (tb[MT76_TM_ATTR_TX_POWER]) {
struct nlattr *cur;
@@ -2563,7 +2564,7 @@
nla_for_each_nested(cur, tb[MT76_TM_ATTR_TX_POWER], rem) {
if (nla_len(cur) != 1 ||
-@@ -505,11 +638,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -505,11 +639,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (nla_len(cur) != ETH_ALEN || idx >= 3)
goto out;
@@ -2610,7 +2611,7 @@
if (dev->test_ops->set_params) {
err = dev->test_ops->set_params(phy, tb, state);
if (err)
-@@ -574,6 +741,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -574,6 +742,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
struct mt76_testmode_data *td = &phy->test;
@@ -2618,7 +2619,7 @@
struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
int err = 0;
void *a;
-@@ -606,6 +774,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -606,6 +775,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
goto out;
}
@@ -2638,7 +2639,7 @@
mt76_testmode_init_defaults(phy);
err = -EMSGSIZE;
-@@ -618,12 +799,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -618,12 +800,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
goto out;
if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
@@ -2651,7 +2652,7 @@
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
-@@ -643,6 +820,15 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -643,6 +821,15 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
goto out;
@@ -2668,7 +2669,7 @@
a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
if (!a)
diff --git a/testmode.h b/testmode.h
-index 8961326..57949f2 100644
+index 89613266..57949f2b 100644
--- a/testmode.h
+++ b/testmode.h
@@ -6,6 +6,8 @@
@@ -2773,7 +2774,7 @@
+
#endif
diff --git a/tools/fields.c b/tools/fields.c
-index e3f6908..6e36ab2 100644
+index e3f69089..6e36ab27 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -2899,7 +2900,7 @@
};
diff --git a/tx.c b/tx.c
-index 02067ed..0457c3e 100644
+index 6c8d50d3..ae44afe0 100644
--- a/tx.c
+++ b/tx.c
@@ -245,8 +245,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
diff --git a/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch b/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch
old mode 100644
new mode 100755
index e077acf..bb06dff
--- a/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch
+++ b/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch
@@ -1,19 +1,21 @@
-From 23de5ffe66f73e5fbd22a441f7ca1f612f1bd158 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Wed, 22 Jun 2022 10:58:37 +0800
-Subject: [PATCH 1113/1115] mt76: mt7915: drop packets when TWT stations use
- more tokens than 128
+From 9bc707077df60aa6423c89b1d17fd8a5f4e2d36b Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 4 Jul 2022 19:24:34 +0800
+Subject: [PATCH] mt76: mt7915: drop packets when TWT stations use
---
mt7915/mac.c | 21 ++++++++++++++++++---
mt7915/mt7915.h | 2 ++
2 files changed, 20 insertions(+), 3 deletions(-)
+ mode change 100644 => 100755 mt7915/mac.c
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 8fd4618..fd0dd50 100644
+old mode 100644
+new mode 100755
+index 5e5df23d..55b38d16
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
-@@ -724,6 +724,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -725,6 +725,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
@@ -21,7 +23,7 @@
struct mt76_connac_fw_txp *txp;
struct mt76_txwi_cache *t;
int id, i, nbuf = tx_info->nbuf - 1;
-@@ -737,8 +738,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -738,8 +739,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
wcid = &dev->mt76.global_wcid;
if (sta) {
@@ -30,7 +32,7 @@
msta = (struct mt7915_sta *)sta->drv_priv;
if (time_after(jiffies, msta->jiffies + HZ / 4)) {
-@@ -754,10 +753,22 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -755,10 +754,22 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
mgmt->u.action.category == 0xff)
return -1;
@@ -51,9 +53,9 @@
+ spin_unlock_bh(&mdev->token_lock);
+
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
- mt7915_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, pid, key, 0);
-
-@@ -937,6 +948,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+ mt7915_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, pid, key,
+ qid, 0);
+@@ -939,6 +950,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
@@ -61,7 +63,7 @@
LIST_HEAD(free_list);
void *end = data + len;
bool v3, wake = false;
-@@ -960,7 +972,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+@@ -962,7 +974,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
* 1'b0: msdu_id with the same 'wcid pair' as above.
*/
if (info & MT_TX_FREE_PAIR) {
@@ -69,7 +71,7 @@
struct mt76_wcid *wcid;
u16 idx;
-@@ -993,6 +1004,10 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+@@ -995,6 +1006,10 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
txwi = mt76_token_release(mdev, msdu, &wake);
if (!txwi)
continue;
@@ -81,7 +83,7 @@
mt7915_txwi_free(dev, txwi, sta, &free_list);
}
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index ff92e55..6235014 100644
+index 7c7d6bd3..5f11b3fb 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -136,6 +136,8 @@ struct mt7915_sta {
diff --git a/recipes-kernel/linux-mt76/files/patches/1116-mt76-mt7915-add-vendor-dump-phy-capa.patch b/recipes-kernel/linux-mt76/files/patches/1116-mt76-mt7915-add-vendor-dump-phy-capa.patch
new file mode 100644
index 0000000..df0838e
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1116-mt76-mt7915-add-vendor-dump-phy-capa.patch
@@ -0,0 +1,130 @@
+Index: mt76-2022-06-24-b6e865e2/mt7915/vendor.c
+===================================================================
+--- mt76-2022-06-24-b6e865e2.orig/mt7915/vendor.c
++++ mt76-2022-06-24-b6e865e2/mt7915/vendor.c
+@@ -50,6 +50,18 @@ rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTR
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 },
+ };
+
++static const struct nla_policy
++phy_capa_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_CTRL] = {
++ [MTK_VENDOR_ATTR_PHY_CAPA_CTRL_SET] = { .type = NLA_NESTED },
++ [MTK_VENDOR_ATTR_PHY_CAPA_CTRL_DUMP] = { .type = NLA_NESTED },
++};
++
++static const struct nla_policy
++phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = {
++ [MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_BSS] = { .type = NLA_U16 },
++ [MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_STA] = { .type = NLA_U16 },
++};
++
+ struct csi_null_tone {
+ u8 start;
+ u8 end;
+@@ -974,6 +986,35 @@ static int mt7915_vendor_hemu_ctrl(struc
+ return 0;
+ }
+
++static int
++mt7915_vendor_phy_capa_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++ struct sk_buff *skb, const void *data, int data_len,
++ unsigned long *storage)
++{
++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++ struct mt7915_phy *phy = mt7915_hw_phy(hw);
++ struct mt7915_dev *dev = phy->dev;
++ void *a;
++ int len = 0;
++
++ if (*storage == 1)
++ return -ENOENT;
++ *storage = 1;
++
++ a = nla_nest_start(skb, MTK_VENDOR_ATTR_PHY_CAPA_CTRL_DUMP);
++
++ if (nla_put_u16(skb,
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_BSS, MT7915_MAX_BSS) ||
++ nla_put_u16(skb,
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_STA, MT7915_WTBL_STA))
++ return -ENOMEM;
++ len += 2;
++
++ nla_nest_end(skb, a);
++
++ return len;
++}
++
+ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ {
+ .info = {
+@@ -1031,6 +1072,17 @@ static const struct wiphy_vendor_command
+ .doit = mt7915_vendor_hemu_ctrl,
+ .policy = hemu_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_HEMU_CTRL_MAX,
++ },
++ {
++ .info = {
++ .vendor_id = MTK_NL80211_VENDOR_ID,
++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL,
++ },
++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++ WIPHY_VENDOR_CMD_NEED_RUNNING,
++ .dumpit = mt7915_vendor_phy_capa_ctrl_dump,
++ .policy = phy_capa_ctrl_policy,
++ .maxattr = MTK_VENDOR_ATTR_PHY_CAPA_CTRL_MAX,
+ }
+ };
+
+Index: mt76-2022-06-24-b6e865e2/mt7915/vendor.h
+===================================================================
+--- mt76-2022-06-24-b6e865e2.orig/mt7915/vendor.h
++++ mt76-2022-06-24-b6e865e2/mt7915/vendor.h
+@@ -9,6 +9,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
+ MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
+ MTK_NL80211_VENDOR_SUBCMD_HEMU_CTRL = 0xc5,
++ MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL = 0xc6,
+ };
+
+ enum mtk_capi_control_changed {
+@@ -149,4 +150,28 @@ enum mtk_vendor_attr_mnt_dump {
+ NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1
+ };
+
++enum mtk_vendor_attr_phy_capa_ctrl {
++ MTK_VENDOR_ATTR_PHY_CAPA_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_PHY_CAPA_CTRL_SET,
++ MTK_VENDOR_ATTR_PHY_CAPA_CTRL_DUMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_PHY_CAPA_CTRL,
++ MTK_VENDOR_ATTR_PHY_CAPA_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_PHY_CAPA_CTRL - 1
++};
++
++enum mtk_vendor_attr_phy_capa_dump {
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_UNSPEC,
++
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_BSS,
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_STA,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP,
++ MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP - 1
++};
++
+ #endif
+Index: mt76-2022-06-24-b6e865e2/mt7915/mt7915.h
+===================================================================
+--- mt76-2022-06-24-b6e865e2.orig/mt7915/mt7915.h
++++ mt76-2022-06-24-b6e865e2/mt7915/mt7915.h
+@@ -11,6 +11,7 @@
+
+ #define MTK_DEBUG 1
+ #define MT7915_MAX_INTERFACES 19
++#define MT7915_MAX_BSS 16
+ #define MT7915_WTBL_SIZE 288
+ #define MT7916_WTBL_SIZE 544
+ #define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1)
diff --git a/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch b/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch
deleted file mode 100644
index 2ef225a..0000000
--- a/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch
+++ /dev/null
@@ -1,1123 +0,0 @@
-From f4838210b5e80adfa3af028721ee040edff79a48 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Mon, 6 Jun 2022 20:22:35 +0800
-Subject: [PATCH] mt76:remove WED support patch for build err
-
----
- dma.c | 160 ++++++++++--------------------------------------
- mac80211.c | 4 +-
- mmio.c | 9 +--
- mt76.h | 25 ++------
- mt7603/dma.c | 8 +--
- mt7615/dma.c | 6 +-
- mt76x02_mmio.c | 4 +-
- mt7915/dma.c | 43 ++-----------
- mt7915/mac.c | 139 ++++++++++-------------------------------
- mt7915/mac.h | 2 -
- mt7915/main.c | 36 -----------
- mt7915/mcu.c | 3 -
- mt7915/mmio.c | 29 +++------
- mt7915/mt7915.h | 2 -
- mt7915/pci.c | 96 +++--------------------------
- mt7915/regs.h | 17 +----
- mt7921/dma.c | 2 +-
- tx.c | 16 +----
- 18 files changed, 105 insertions(+), 496 deletions(-)
-
-diff --git a/dma.c b/dma.c
-index f6f5f12..3f7456b 100644
---- a/dma.c
-+++ b/dma.c
-@@ -7,36 +7,9 @@
- #include "mt76.h"
- #include "dma.h"
-
--#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
--
--#define Q_READ(_dev, _q, _field) ({ \
-- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
-- u32 _val; \
-- if ((_q)->flags & MT_QFLAG_WED) \
-- _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \
-- ((_q)->wed_regs + \
-- _offset)); \
-- else \
-- _val = readl(&(_q)->regs->_field); \
-- _val; \
--})
--
--#define Q_WRITE(_dev, _q, _field, _val) do { \
-- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
-- if ((_q)->flags & MT_QFLAG_WED) \
-- mtk_wed_device_reg_write(&(_dev)->mmio.wed, \
-- ((_q)->wed_regs + _offset), \
-- _val); \
-- else \
-- writel(_val, &(_q)->regs->_field); \
--} while (0)
--
--#else
--
--#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field)
--#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field)
-+#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field)
-+#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field)
-
--#endif
-
- static struct mt76_txwi_cache *
- mt76_alloc_txwi(struct mt76_dev *dev)
-@@ -138,6 +111,36 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
- mt76_dma_sync_idx(dev, q);
- }
-
-+static int
-+mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
-+ int idx, int n_desc, int bufsize,
-+ u32 ring_base)
-+{
-+ int size;
-+
-+ spin_lock_init(&q->lock);
-+ spin_lock_init(&q->cleanup_lock);
-+
-+ q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
-+ q->ndesc = n_desc;
-+ q->buf_size = bufsize;
-+ q->hw_idx = idx;
-+
-+ size = q->ndesc * sizeof(struct mt76_desc);
-+ q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
-+ if (!q->desc)
-+ return -ENOMEM;
-+
-+ size = q->ndesc * sizeof(*q->entry);
-+ q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
-+ if (!q->entry)
-+ return -ENOMEM;
-+
-+ mt76_dma_queue_reset(dev, q);
-+
-+ return 0;
-+}
-+
- static int
- mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
- struct mt76_queue_buf *buf, int nbufs, u32 info,
-@@ -482,85 +485,6 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
- return frames;
- }
-
--static int
--mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
--{
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-- struct mtk_wed_device *wed = &dev->mmio.wed;
-- int ret, type, ring;
-- u8 flags = q->flags;
--
-- if (!mtk_wed_device_active(wed))
-- q->flags &= ~MT_QFLAG_WED;
--
-- if (!(q->flags & MT_QFLAG_WED))
-- return 0;
--
-- type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
-- ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
--
-- switch (type) {
-- case MT76_WED_Q_TX:
-- ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs);
-- if (!ret)
-- q->wed_regs = wed->tx_ring[ring].reg_base;
-- break;
-- case MT76_WED_Q_TXFREE:
-- /* WED txfree queue needs ring to be initialized before setup */
-- q->flags = 0;
-- mt76_dma_queue_reset(dev, q);
-- mt76_dma_rx_fill(dev, q);
-- q->flags = flags;
--
-- ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-- if (!ret)
-- q->wed_regs = wed->txfree_ring.reg_base;
-- break;
-- default:
-- ret = -EINVAL;
-- }
--
-- return ret;
--#else
-- return 0;
--#endif
--}
--
--static int
--mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
-- int idx, int n_desc, int bufsize,
-- u32 ring_base)
--{
-- int ret, size;
--
-- spin_lock_init(&q->lock);
-- spin_lock_init(&q->cleanup_lock);
--
-- q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
-- q->ndesc = n_desc;
-- q->buf_size = bufsize;
-- q->hw_idx = idx;
--
-- size = q->ndesc * sizeof(struct mt76_desc);
-- q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
-- if (!q->desc)
-- return -ENOMEM;
--
-- size = q->ndesc * sizeof(*q->entry);
-- q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
-- if (!q->entry)
-- return -ENOMEM;
--
-- ret = mt76_dma_wed_setup(dev, q);
-- if (ret)
-- return ret;
--
-- if (q->flags != MT_WED_Q_TXFREE)
-- mt76_dma_queue_reset(dev, q);
--
-- return 0;
--}
--
- static void
- mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
- {
-@@ -642,29 +566,14 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
- static int
- mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
- {
-- int len, data_len, done = 0, dma_idx;
-+ int len, data_len, done = 0;
- struct sk_buff *skb;
- unsigned char *data;
-- bool check_ddone = false;
- bool more;
-
-- if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
-- q->flags == MT_WED_Q_TXFREE) {
-- dma_idx = Q_READ(dev, q, dma_idx);
-- check_ddone = true;
-- }
--
- while (done < budget) {
- u32 info;
-
-- if (check_ddone) {
-- if (q->tail == dma_idx)
-- dma_idx = Q_READ(dev, q, dma_idx);
--
-- if (q->tail == dma_idx)
-- break;
-- }
--
- data = mt76_dma_dequeue(dev, q, false, &len, &info, &more);
- if (!data)
- break;
-@@ -805,8 +714,5 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
- }
-
- mt76_free_pending_txwi(dev);
--
-- if (mtk_wed_device_active(&dev->mmio.wed))
-- mtk_wed_device_detach(&dev->mmio.wed);
- }
- EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
-diff --git a/mac80211.c b/mac80211.c
-index 5600a09..7878446 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -1605,7 +1605,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
-
- struct mt76_queue *
- mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
-- int ring_base, u32 flags)
-+ int ring_base)
- {
- struct mt76_queue *hwq;
- int err;
-@@ -1614,8 +1614,6 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
- if (!hwq)
- return ERR_PTR(-ENOMEM);
-
-- hwq->flags = flags;
--
- err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
- if (err < 0)
- return ERR_PTR(err);
-diff --git a/mmio.c b/mmio.c
-index 86e3d2a..26353b6 100644
---- a/mmio.c
-+++ b/mmio.c
-@@ -73,13 +73,8 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
- spin_lock_irqsave(&dev->mmio.irq_lock, flags);
- dev->mmio.irqmask &= ~clear;
- dev->mmio.irqmask |= set;
-- if (addr) {
-- if (mtk_wed_device_active(&dev->mmio.wed))
-- mtk_wed_device_irq_set_mask(&dev->mmio.wed,
-- dev->mmio.irqmask);
-- else
-- mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
-- }
-+ if (addr)
-+ mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
- spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
- }
- EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
-diff --git a/mt76.h b/mt76.h
-index 062c5ce..ed1924c 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -13,7 +13,6 @@
- #include <linux/leds.h>
- #include <linux/usb.h>
- #include <linux/average.h>
--#include <linux/soc/mediatek/mtk_wed.h>
- #include <net/mac80211.h>
- #include "util.h"
- #include "testmode.h"
-@@ -27,16 +26,6 @@
-
- #define MT76_TOKEN_FREE_THR 64
-
--#define MT_QFLAG_WED_RING GENMASK(1, 0)
--#define MT_QFLAG_WED_TYPE GENMASK(3, 2)
--#define MT_QFLAG_WED BIT(4)
--
--#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
-- FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
-- FIELD_PREP(MT_QFLAG_WED_RING, _n))
--#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
--#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
--
- struct mt76_dev;
- struct mt76_phy;
- struct mt76_wcid;
-@@ -186,9 +175,6 @@ struct mt76_queue {
- u8 buf_offset;
- u8 hw_idx;
- u8 qid;
-- u8 flags;
--
-- u32 wed_regs;
-
- dma_addr_t desc_dma;
- struct sk_buff *rx_head;
-@@ -556,8 +542,6 @@ struct mt76_mmio {
- void __iomem *regs;
- spinlock_t irq_lock;
- u32 irqmask;
--
-- struct mtk_wed_device wed;
- };
-
- struct mt76_rx_status {
-@@ -782,7 +766,6 @@ struct mt76_dev {
-
- spinlock_t token_lock;
- struct idr token;
-- u16 wed_token_count;
- u16 token_count;
- u16 token_size;
-
-@@ -1008,14 +991,14 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
-
- struct mt76_queue *
- mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
-- int ring_base, u32 flags);
-+ int ring_base);
- u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
- static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
-- int n_desc, int ring_base, u32 flags)
-+ int n_desc, int ring_base)
- {
- struct mt76_queue *q;
-
-- q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags);
-+ q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base);
- if (IS_ERR(q))
- return PTR_ERR(q);
-
-@@ -1030,7 +1013,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
- {
- struct mt76_queue *q;
-
-- q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0);
-+ q = mt76_init_queue(dev, qid, idx, n_desc, ring_base);
- if (IS_ERR(q))
- return PTR_ERR(q);
-
-diff --git a/mt7603/dma.c b/mt7603/dma.c
-index 590cff9..37b092e 100644
---- a/mt7603/dma.c
-+++ b/mt7603/dma.c
-@@ -173,13 +173,13 @@ int mt7603_dma_init(struct mt7603_dev *dev)
-
- for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
- ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
-- MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0);
-+ MT7603_TX_RING_SIZE, MT_TX_RING_BASE);
- if (ret)
- return ret;
- }
-
- ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
-- MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
-+ MT7603_PSD_RING_SIZE, MT_TX_RING_BASE);
- if (ret)
- return ret;
-
-@@ -189,12 +189,12 @@ int mt7603_dma_init(struct mt7603_dev *dev)
- return ret;
-
- ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN,
-- MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
-+ MT_MCU_RING_SIZE, MT_TX_RING_BASE);
- if (ret)
- return ret;
-
- ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC,
-- MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
-+ MT_MCU_RING_SIZE, MT_TX_RING_BASE);
- if (ret)
- return ret;
-
-diff --git a/mt7615/dma.c b/mt7615/dma.c
-index 3a79a2d..00aefea 100644
---- a/mt7615/dma.c
-+++ b/mt7615/dma.c
-@@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
- for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
- ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
- MT7615_TX_RING_SIZE / 2,
-- MT_TX_RING_BASE, 0);
-+ MT_TX_RING_BASE);
- if (ret)
- return ret;
- }
-
- ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT,
- MT7615_TX_MGMT_RING_SIZE,
-- MT_TX_RING_BASE, 0);
-+ MT_TX_RING_BASE);
- if (ret)
- return ret;
-
-@@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
- return mt7622_init_tx_queues_multi(dev);
-
- ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE,
-- MT_TX_RING_BASE, 0);
-+ MT_TX_RING_BASE);
- if (ret)
- return ret;
-
-diff --git a/mt76x02_mmio.c b/mt76x02_mmio.c
-index 0fa3c7c..8bcd8af 100644
---- a/mt76x02_mmio.c
-+++ b/mt76x02_mmio.c
-@@ -191,13 +191,13 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i),
- MT76x02_TX_RING_SIZE,
-- MT_TX_RING_BASE, 0);
-+ MT_TX_RING_BASE);
- if (ret)
- return ret;
- }
-
- ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
-- MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
-+ MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE);
- if (ret)
- return ret;
-
-diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 9e3d14d..4358e9b 100644
---- a/mt7915/dma.c
-+++ b/mt7915/dma.c
-@@ -8,16 +8,9 @@
- static int
- mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
- {
-- struct mt7915_dev *dev = phy->dev;
- int i, err;
-
-- if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
-- ring_base = MT_WED_TX_RING_BASE;
-- idx -= MT_TXQ_ID(0);
-- }
--
-- err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base,
-- MT_WED_Q_TX(idx));
-+ err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base);
- if (err < 0)
- return err;
-
-@@ -326,14 +319,6 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
- if (dev->dbdc_support || dev->phy.band_idx)
- irq_mask |= MT_INT_BAND1_RX_DONE;
-
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-- u32 wed_irq_mask = irq_mask;
--
-- wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
-- mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
-- mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
-- }
--
- mt7915_irq_enable(dev, irq_mask);
-
- return 0;
-@@ -342,7 +327,6 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
- int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
- {
- struct mt76_dev *mdev = &dev->mt76;
-- u32 wa_rx_base, wa_rx_idx;
- u32 hif1_ofs = 0;
- int ret;
-
-@@ -355,17 +339,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
-
- mt7915_dma_disable(dev, true);
-
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-- mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
--
-- mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
-- FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
-- FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
-- FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
-- } else {
-- mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
-- }
--
- /* init tx queue */
- ret = mt7915_init_tx_queues(&dev->phy,
- MT_TXQ_ID(dev->phy.band_idx),
-@@ -417,17 +390,11 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
- return ret;
-
- /* event from WA */
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-- wa_rx_base = MT_WED_RX_RING_BASE;
-- wa_rx_idx = MT7915_RXQ_MCU_WA;
-- dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
-- } else {
-- wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA);
-- wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA);
-- }
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
-- wa_rx_idx, MT7915_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE, wa_rx_base);
-+ MT_RXQ_ID(MT_RXQ_MCU_WA),
-+ MT7915_RX_MCU_RING_SIZE,
-+ MT_RX_BUF_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
- if (ret)
- return ret;
-
-diff --git a/mt7915/mac.c b/mt7915/mac.c
-index fd0dd50..1bf3b41 100644
---- a/mt7915/mac.c
-+++ b/mt7915/mac.c
-@@ -815,29 +815,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- return 0;
- }
-
--u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
--{
-- struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE;
-- __le32 *txwi = ptr;
-- u32 val;
--
-- memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
--
-- val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
-- FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
-- txwi[0] = cpu_to_le32(val);
--
-- val = MT_TXD1_LONG_FORMAT |
-- FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
-- txwi[1] = cpu_to_le32(val);
--
-- txp->token = cpu_to_le16(token_id);
-- txp->nbuf = 1;
-- txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
--
-- return MT_TXD_SIZE + sizeof(*txp);
--}
--
- static void
- mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- {
-@@ -863,12 +840,23 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- ieee80211_start_tx_ba_session(sta, tid, 0);
- }
-
-+/* static void */
-+/* mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t) */
-+/* { */
-+/* struct mt76_connac_fw_txp *txp; */
-+/* int i; */
-+
-+/* txp = mt76_connac_txwi_to_txp(dev, t); */
-+/* for (i = 0; i < txp->nbuf; i++) */
-+/* dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), */
-+/* le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); */
-+/* } */
-+
- static void
- mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, struct list_head *free_list)
- {
- struct mt76_dev *mdev = &dev->mt76;
-- struct mt7915_sta *msta;
- struct mt76_wcid *wcid;
- __le32 *txwi;
- u16 wcid_idx;
-@@ -881,24 +869,13 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
- if (sta) {
- wcid = (struct mt76_wcid *)sta->drv_priv;
- wcid_idx = wcid->idx;
-+
-+ if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-+ mt7915_tx_check_aggr(sta, txwi);
- } else {
- wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
-- wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]);
--
-- if (wcid && wcid->sta) {
-- msta = container_of(wcid, struct mt7915_sta, wcid);
-- sta = container_of((void *)msta, struct ieee80211_sta,
-- drv_priv);
-- spin_lock_bh(&dev->sta_poll_lock);
-- if (list_empty(&msta->poll_list))
-- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
-- spin_unlock_bh(&dev->sta_poll_lock);
-- }
- }
-
-- if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-- mt7915_tx_check_aggr(sta, txwi);
--
- __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
-
- out:
-@@ -906,57 +883,31 @@ out:
- mt76_put_txwi(mdev, t);
- }
-
--static void
--mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
--{
-- struct mt76_dev *mdev = &dev->mt76;
-- struct mt76_phy *mphy_ext = mdev->phy2;
--
-- /* clean DMA queues and unmap buffers first */
-- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
-- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
-- if (mphy_ext) {
-- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
-- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
-- }
--}
--
--static void
--mt7915_mac_tx_free_done(struct mt7915_dev *dev,
-- struct list_head *free_list, bool wake)
--{
-- struct sk_buff *skb, *tmp;
--
-- mt7915_mac_sta_poll(dev);
--
-- if (wake)
-- mt76_set_tx_blocked(&dev->mt76, false);
--
-- mt76_worker_schedule(&dev->mt76.tx_worker);
--
-- list_for_each_entry_safe(skb, tmp, free_list, list) {
-- skb_list_del_init(skb);
-- napi_consume_skb(skb, 1);
-- }
--}
--
- static void
- mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
- {
- struct mt76_connac_tx_free *free = data;
- __le32 *tx_info = (__le32 *)(data + sizeof(*free));
- struct mt76_dev *mdev = &dev->mt76;
-+ struct mt76_phy *mphy_ext = mdev->phy2;
- struct mt76_txwi_cache *txwi;
- struct ieee80211_sta *sta = NULL;
- struct mt7915_sta *msta = NULL;
- LIST_HEAD(free_list);
-+ struct sk_buff *skb, *tmp;
- void *end = data + len;
- bool v3, wake = false;
- u16 total, count = 0;
- u32 txd = le32_to_cpu(free->txd);
- __le32 *cur_info;
-
-- mt7915_mac_tx_free_prepare(dev);
-+ /* clean DMA queues and unmap buffers first */
-+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
-+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
-+ if (mphy_ext) {
-+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
-+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
-+ }
-
- total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
- v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
-@@ -1013,38 +964,17 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
- }
- }
-
-- mt7915_mac_tx_free_done(dev, &free_list, wake);
--}
--
--static void
--mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len)
--{
-- struct mt76_connac_tx_free *free = data;
-- __le16 *info = (__le16 *)(data + sizeof(*free));
-- struct mt76_dev *mdev = &dev->mt76;
-- void *end = data + len;
-- LIST_HEAD(free_list);
-- bool wake = false;
-- u8 i, count;
--
-- mt7915_mac_tx_free_prepare(dev);
--
-- count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl));
-- if (WARN_ON_ONCE((void *)&info[count] > end))
-- return;
-+ mt7915_mac_sta_poll(dev);
-
-- for (i = 0; i < count; i++) {
-- struct mt76_txwi_cache *txwi;
-- u16 msdu = le16_to_cpu(info[i]);
-+ if (wake)
-+ mt76_set_tx_blocked(&dev->mt76, false);
-
-- txwi = mt76_token_release(mdev, msdu, &wake);
-- if (!txwi)
-- continue;
-+ mt76_worker_schedule(&dev->mt76.tx_worker);
-
-- mt7915_txwi_free(dev, txwi, NULL, &free_list);
-+ list_for_each_entry_safe(skb, tmp, &free_list, list) {
-+ skb_list_del_init(skb);
-+ napi_consume_skb(skb, 1);
- }
--
-- mt7915_mac_tx_free_done(dev, &free_list, wake);
- }
-
- static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
-@@ -1102,9 +1032,6 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
- case PKT_TYPE_TXRX_NOTIFY:
- mt7915_mac_tx_free(dev, data, len);
- return false;
-- case PKT_TYPE_TXRX_NOTIFY_V0:
-- mt7915_mac_tx_free_v0(dev, data, len);
-- return false;
- case PKT_TYPE_TXS:
- for (rxd += 2; rxd + 8 <= end; rxd += 8)
- mt7915_mac_add_txs(dev, rxd);
-@@ -1132,10 +1059,6 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- mt7915_mac_tx_free(dev, skb->data, skb->len);
- napi_consume_skb(skb, 1);
- break;
-- case PKT_TYPE_TXRX_NOTIFY_V0:
-- mt7915_mac_tx_free_v0(dev, skb->data, skb->len);
-- napi_consume_skb(skb, 1);
-- break;
- case PKT_TYPE_RX_EVENT:
- mt7915_mcu_rx_event(dev, skb);
- break;
-diff --git a/mt7915/mac.h b/mt7915/mac.h
-index 6fa9c79..9986c03 100644
---- a/mt7915/mac.h
-+++ b/mt7915/mac.h
-@@ -26,12 +26,10 @@ enum rx_pkt_type {
- PKT_TYPE_TXRX_NOTIFY,
- PKT_TYPE_RX_EVENT,
- PKT_TYPE_RX_FW_MONITOR = 0x0c,
-- PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
- };
-
- #define MT_TX_FREE_VER GENMASK(18, 16)
- #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
--#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
- #define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
- #define MT_TX_FREE_LATENCY GENMASK(12, 0)
- /* 0: success, others: dropped */
-diff --git a/mt7915/main.c b/mt7915/main.c
-index ebff255..79127b4 100644
---- a/mt7915/main.c
-+++ b/mt7915/main.c
-@@ -1422,39 +1422,6 @@ out:
- return ret;
- }
-
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
--static int
--mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta,
-- struct net_device_path_ctx *ctx,
-- struct net_device_path *path)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct mt7915_dev *dev = mt7915_hw_dev(hw);
-- struct mt7915_phy *phy = mt7915_hw_phy(hw);
-- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
--
-- if (!mtk_wed_device_active(wed))
-- return -ENODEV;
--
-- if (msta->wcid.idx > 0xff)
-- 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 = msta->wcid.idx;
-- path->mtk_wdma.queue = phy != &dev->phy;
--
-- ctx->dev = NULL;
--
-- return 0;
--}
--#endif
--
- const struct ieee80211_ops mt7915_ops = {
- .tx = mt7915_tx,
- .start = mt7915_start,
-@@ -1502,7 +1469,4 @@ const struct ieee80211_ops mt7915_ops = {
- .sta_add_debugfs = mt7915_sta_add_debugfs,
- #endif
- .set_radar_background = mt7915_set_radar_background,
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-- .net_fill_forward_path = mt7915_net_fill_forward_path,
--#endif
- };
-diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index a16081d..46eef36 100644
---- a/mt7915/mcu.c
-+++ b/mt7915/mcu.c
-@@ -2365,9 +2365,6 @@ int mt7915_run_firmware(struct mt7915_dev *dev)
- if (ret)
- return ret;
-
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed))
-- mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
--
- ret = mt7915_mcu_set_mwds(dev, 1);
- if (ret)
- return ret;
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index a84970d..1f58b2f 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -560,21 +560,15 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
- static void mt7915_irq_tasklet(struct tasklet_struct *t)
- {
- struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
-- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
- u32 intr, intr1, mask;
-
-- if (mtk_wed_device_active(wed)) {
-- mtk_wed_device_irq_set_mask(wed, 0);
-- intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
-- } else {
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
-+ if (dev->hif2)
-+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-
-- intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
-- intr &= dev->mt76.mmio.irqmask;
-- mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
-- }
-+ intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
-+ intr &= dev->mt76.mmio.irqmask;
-+ mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
-
- if (dev->hif2) {
- intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
-@@ -628,15 +622,10 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
- irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
- {
- struct mt7915_dev *dev = dev_instance;
-- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-
-- if (mtk_wed_device_active(wed)) {
-- mtk_wed_device_irq_set_mask(wed, 0);
-- } else {
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-- }
-+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
-+ if (dev->hif2)
-+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
- return IRQ_NONE;
-diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 6235014..ca95948 100644
---- a/mt7915/mt7915.h
-+++ b/mt7915/mt7915.h
-@@ -527,8 +527,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
- void mt7915_wfsys_reset(struct mt7915_dev *dev);
- irqreturn_t mt7915_irq_handler(int irq, void *dev_instance);
- u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif);
--u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
--
- int mt7915_register_device(struct mt7915_dev *dev);
- void mt7915_unregister_device(struct mt7915_dev *dev);
- int mt7915_eeprom_init(struct mt7915_dev *dev);
-diff --git a/mt7915/pci.c b/mt7915/pci.c
-index d74f609..7cea49f 100644
---- a/mt7915/pci.c
-+++ b/mt7915/pci.c
-@@ -12,9 +12,6 @@
- #include "mac.h"
- #include "../trace.h"
-
--static bool wed_enable = false;
--module_param(wed_enable, bool, 0644);
--
- static LIST_HEAD(hif_list);
- static DEFINE_SPINLOCK(hif_lock);
- static u32 hif_idx;
-@@ -95,79 +92,12 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
- return 0;
- }
-
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
--static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
--{
-- struct mt7915_dev *dev;
-- int ret;
--
-- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
--
-- spin_lock_bh(&dev->mt76.token_lock);
-- dev->mt76.token_size = wed->wlan.token_start;
-- spin_unlock_bh(&dev->mt76.token_lock);
--
-- ret = wait_event_timeout(dev->mt76.tx_wait,
-- !dev->mt76.wed_token_count, HZ);
-- if (!ret)
-- return -EAGAIN;
--
-- return 0;
--}
--
--static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
--{
-- struct mt7915_dev *dev;
--
-- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
--
-- spin_lock_bh(&dev->mt76.token_lock);
-- dev->mt76.token_size = MT7915_TOKEN_SIZE;
-- spin_unlock_bh(&dev->mt76.token_lock);
--}
--#endif
--
--static int
--mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
--{
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-- int ret;
--
-- if (!wed_enable)
-- return 0;
--
-- wed->wlan.pci_dev = pdev;
-- wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
-- MT_WFDMA_EXT_CSR_BASE;
-- wed->wlan.nbuf = 4096;
-- wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
-- wed->wlan.init_buf = mt7915_wed_init_buf;
-- wed->wlan.offload_enable = mt7915_wed_offload_enable;
-- wed->wlan.offload_disable = mt7915_wed_offload_disable;
--
-- if (mtk_wed_device_attach(wed) != 0)
-- return 0;
--
-- *irq = wed->irq;
-- dev->mt76.dma_dev = wed->dev;
--
-- ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
-- if (ret)
-- return ret;
--
-- return 1;
--#else
-- return 0;
--#endif
--}
--
- static int mt7915_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
- {
-- struct mt7915_hif *hif2 = NULL;
- struct mt7915_dev *dev;
- struct mt76_dev *mdev;
-+ struct mt7915_hif *hif2;
- int irq;
- int ret;
-
-@@ -199,24 +129,15 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
- mt7915_wfsys_reset(dev);
- hif2 = mt7915_pci_init_hif2(pdev);
-
-- ret = mt7915_pci_wed_init(dev, pdev, &irq);
-+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
- if (ret < 0)
-- goto free_wed_or_irq_vector;
--
-- if (!ret) {
-- hif2 = mt7915_pci_init_hif2(pdev);
--
-- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
-- if (ret < 0)
-- goto free_device;
--
-- irq = pdev->irq;
-- }
-+ goto free_device;
-
-+ irq = pdev->irq;
- ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
- if (ret)
-- goto free_wed_or_irq_vector;
-+ goto free_irq_vector;
-
- /* master switch of PCIe tnterrupt enable */
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
-@@ -251,11 +172,8 @@ free_hif2:
- if (dev->hif2)
- put_device(dev->hif2->dev);
- devm_free_irq(mdev->dev, irq, dev);
--free_wed_or_irq_vector:
-- if (mtk_wed_device_active(&mdev->mmio.wed))
-- mtk_wed_device_detach(&mdev->mmio.wed);
-- else
-- pci_free_irq_vectors(pdev);
-+free_irq_vector:
-+ pci_free_irq_vectors(pdev);
- free_device:
- mt76_free_device(&dev->mt76);
-
-diff --git a/mt7915/regs.h b/mt7915/regs.h
-index 444440e..1e7fbce 100644
---- a/mt7915/regs.h
-+++ b/mt7915/regs.h
-@@ -603,31 +603,18 @@ enum offs_rev {
-
- /* WFDMA CSR */
- #define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR)
--#define MT_WFDMA_EXT_CSR_PHYS_BASE 0x18027000
- #define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
--#define MT_WFDMA_EXT_CSR_PHYS(ofs) (MT_WFDMA_EXT_CSR_PHYS_BASE + (ofs))
-
--#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR_PHYS(0x30)
-+#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
- #define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
--#define MT_WFDMA_HOST_CONFIG_WED BIT(1)
-
--#define MT_WFDMA_WED_RING_CONTROL MT_WFDMA_EXT_CSR_PHYS(0x34)
--#define MT_WFDMA_WED_RING_CONTROL_TX0 GENMASK(4, 0)
--#define MT_WFDMA_WED_RING_CONTROL_TX1 GENMASK(12, 8)
--#define MT_WFDMA_WED_RING_CONTROL_RX1 GENMASK(20, 16)
--
--#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR_PHYS(0x44)
-+#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
- #define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
-
- #define MT_PCIE_RECOG_ID 0xd7090
- #define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
- #define MT_PCIE_RECOG_ID_SEM BIT(31)
-
--#define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204)
--
--#define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300)
--#define MT_WED_RX_RING_BASE MT_WFDMA_EXT_CSR(0x400)
--
- /* WFDMA0 PCIE1 */
- #define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR)
- #define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
-diff --git a/mt7921/dma.c b/mt7921/dma.c
-index 2939cf9..ca7e20f 100644
---- a/mt7921/dma.c
-+++ b/mt7921/dma.c
-@@ -9,7 +9,7 @@ static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
- {
- int i, err;
-
-- err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE, 0);
-+ err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE);
- if (err < 0)
- return err;
-
-diff --git a/tx.c b/tx.c
-index 0457c3e..656b709 100644
---- a/tx.c
-+++ b/tx.c
-@@ -725,12 +725,6 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
- if (token >= 0)
- dev->token_count++;
-
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-- if (mtk_wed_device_active(&dev->mmio.wed) &&
-- token >= dev->mmio.wed.wlan.token_start)
-- dev->wed_token_count++;
--#endif
--
- if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR)
- __mt76_set_tx_blocked(dev, true);
-
-@@ -748,17 +742,9 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
- spin_lock_bh(&dev->token_lock);
-
- txwi = idr_remove(&dev->token, token);
-- if (txwi) {
-+ if (txwi)
- dev->token_count--;
-
--#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-- if (mtk_wed_device_active(&dev->mmio.wed) &&
-- token >= dev->mmio.wed.wlan.token_start &&
-- --dev->wed_token_count == 0)
-- wake_up(&dev->tx_wait);
--#endif
-- }
--
- if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
- dev->phy.q_tx[0]->blocked)
- *wake = true;
---
-2.18.0
-
diff --git a/recipes-kernel/linux-mt76/files/patches/3001-mt76-add-wed-tx-support.patch b/recipes-kernel/linux-mt76/files/patches/3001-mt76-add-wed-tx-support.patch
new file mode 100755
index 0000000..e83baf5
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/3001-mt76-add-wed-tx-support.patch
@@ -0,0 +1,554 @@
+From c5d0d7fb936620a3737fe5b71c1f59170ba42674 Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Sun, 12 Jun 2022 16:38:45 +0800
+Subject: [PATCH 1/3] mt76 add wed tx support
+
+Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
+---
+ mt76_connac.h | 1 +
+ mt7915/dma.c | 59 +++++++++++++++++++-------
+ mt7915/mac.c | 4 +-
+ mt7915/mac.h | 0
+ mt7915/main.c | 9 +++-
+ mt7915/mcu.c | 2 +-
+ mt7915/mmio.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
+ mt7915/mt7915.h | 2 +
+ mt7915/pci.c | 72 +------------------------------
+ mt7915/regs.h | 15 +++++++
+ mt7915/soc.c | 16 +++++--
+ 11 files changed, 193 insertions(+), 97 deletions(-)
+ mode change 100644 => 100755 mt76_connac.h
+ mode change 100644 => 100755 mt7915/mac.h
+ mode change 100644 => 100755 mt7915/mmio.c
+
+diff --git a/mt76_connac.h b/mt76_connac.h
+old mode 100644
+new mode 100755
+index 1d32d55b..3c493014
+--- a/mt76_connac.h
++++ b/mt76_connac.h
+@@ -110,6 +110,7 @@ struct mt76_connac_sta_key_conf {
+ };
+
+ #define MT_TXP_MAX_BUF_NUM 6
++#define MT_TXD_TXP_BUF_SIZE 128
+
+ struct mt76_connac_fw_txp {
+ __le16 flags;
+diff --git a/mt7915/dma.c b/mt7915/dma.c
+index 9e3d14db..71223221 100644
+--- a/mt7915/dma.c
++++ b/mt7915/dma.c
+@@ -12,7 +12,10 @@ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base
+ int i, err;
+
+ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
+- ring_base = MT_WED_TX_RING_BASE;
++ if(!is_mt7986(&dev->mt76))
++ ring_base = MT_WED_TX_RING_BASE;
++ else
++ ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
+ idx -= MT_TXQ_ID(0);
+ }
+
+@@ -74,14 +77,23 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
+ MCUQ_CONFIG(MT_MCUQ_WA, WFDMA1, MT_INT_TX_DONE_MCU_WA, MT7915_TXQ_MCU_WA);
+ MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA1, MT_INT_TX_DONE_FWDL, MT7915_TXQ_FWDL);
+ } else {
+- RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0);
++ if(is_mt7916(&dev->mt76) && (mtk_wed_device_active(&dev->mt76.mmio.wed))) {
++ RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_WED_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0);
++ RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916, MT7916_RXQ_MCU_WA);
++ RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
++ RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN);
++ TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0, MT7915_TXQ_BAND0);
++ TXQ_CONFIG(1, WFDMA0, MT_INT_WED_TX_DONE_BAND1, MT7915_TXQ_BAND1);
++ } else {
++ RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0);
++ RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7916_RXQ_MCU_WA);
++ RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
++ RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN);
++ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
++ TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
++ }
+ RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7916_RXQ_MCU_WM);
+- RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7916_RXQ_MCU_WA);
+- RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
+ RXQ_CONFIG(MT_RXQ_EXT_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT);
+- RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN);
+- TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
+- TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
+ MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7915_TXQ_MCU_WM);
+ MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA_MT7916, MT7915_TXQ_MCU_WA);
+ MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7915_TXQ_FWDL);
+@@ -330,7 +342,9 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
+ u32 wed_irq_mask = irq_mask;
+
+ wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
+- mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
++ if (!is_mt7986(&dev->mt76))
++ mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
++ mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
+ mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
+ }
+
+@@ -355,15 +369,19 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+
+ mt7915_dma_disable(dev, true);
+
+- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && !is_mt7986(mdev)) {
+ mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
+-
++ if(is_mt7915(mdev)) {
+ mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
+- } else {
+- mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
++ } else {
++ mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
++ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
++ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
++ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 2));
++ }
+ }
+
+ /* init tx queue */
+@@ -417,7 +435,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ return ret;
+
+ /* event from WA */
+- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(mdev)) {
+ wa_rx_base = MT_WED_RX_RING_BASE;
+ wa_rx_idx = MT7915_RXQ_MCU_WA;
+ dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
+@@ -444,11 +462,20 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+
+ /* tx free notify event from WA for band0 */
+ if (!is_mt7915(mdev)) {
++ wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA);
++ wa_rx_idx = MT_RXQ_ID(MT_RXQ_MAIN_WA);
++
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++ dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
++ if (is_mt7916(mdev)) {
++ wa_rx_base = MT_WED_RX_RING_BASE;
++ wa_rx_idx = MT7915_RXQ_MCU_WA;
++ }
++ }
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
+- MT_RXQ_ID(MT_RXQ_MAIN_WA),
++ wa_rx_idx,
+ MT7915_RX_MCU_RING_SIZE,
+- MT_RX_BUF_SIZE,
+- MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA));
++ MT_RX_BUF_SIZE, wa_rx_base);
+ if (ret)
+ return ret;
+ }
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index fd0dd509..3f059bed 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -833,9 +833,9 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+
+ txp->token = cpu_to_le16(token_id);
+ txp->nbuf = 1;
+- txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
++ txp->buf[0] = cpu_to_le32(phys + MT_TXD_TXP_BUF_SIZE);
+
+- return MT_TXD_SIZE + sizeof(*txp);
++ return MT_TXD_TXP_BUF_SIZE;
+ }
+
+ static void
+diff --git a/mt7915/mac.h b/mt7915/mac.h
+old mode 100644
+new mode 100755
+diff --git a/mt7915/main.c b/mt7915/main.c
+index ebff255f..f1396eed 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -1439,14 +1439,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 = msta->wcid.idx;
++ /* fw will find the wcid by dest addr */
++ if(is_mt7915(&dev->mt76))
++ path->mtk_wdma.wcid = 0xff;
++ else
++ path->mtk_wdma.wcid = 0x3ff;
++
+ path->mtk_wdma.queue = phy != &dev->phy;
+
+ ctx->dev = NULL;
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 3344e122..9d2a7059 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -2362,7 +2362,7 @@ int mt7915_run_firmware(struct mt7915_dev *dev)
+ if (ret)
+ return ret;
+
+- if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++ 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);
+
+ ret = mt7915_mcu_set_mwds(dev, 1);
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+old mode 100644
+new mode 100755
+index 6d1dbdbd..b4a3120d
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -10,6 +10,9 @@
+ #include "mac.h"
+ #include "../trace.h"
+
++static bool wed_enable = true;
++module_param(wed_enable, bool, 0644);
++
+ static const u32 mt7915_reg[] = {
+ [INT_SOURCE_CSR] = 0xd7010,
+ [INT_MASK_CSR] = 0xd7014,
+@@ -541,7 +544,11 @@ void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev,
+ mdev->mmio.irqmask |= set;
+
+ if (write_reg) {
+- mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
++ if (mtk_wed_device_active(&mdev->mmio.wed))
++ mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
++ mdev->mmio.irqmask);
++ else
++ mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
+ mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
+ }
+
+@@ -565,6 +572,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
+
+ if (mtk_wed_device_active(wed)) {
+ mtk_wed_device_irq_set_mask(wed, 0);
++ if (dev->hif2)
++ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
+ } else {
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
+@@ -646,6 +655,105 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
+ return IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
++{
++ struct mt7915_dev *dev;
++ int ret;
++
++ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
++
++ spin_lock_bh(&dev->mt76.token_lock);
++ dev->mt76.token_size = wed->wlan.token_start;
++ spin_unlock_bh(&dev->mt76.token_lock);
++
++ ret = wait_event_timeout(dev->mt76.tx_wait,
++ !dev->mt76.wed_token_count, HZ);
++ if (!ret)
++ return -EAGAIN;
++
++ return 0;
++}
++
++static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
++{
++ struct mt7915_dev *dev;
++
++ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
++
++ spin_lock_bh(&dev->mt76.token_lock);
++ dev->mt76.token_size = wed->wlan.token_start;//MT7915_TOKEN_SIZE;
++ spin_unlock_bh(&dev->mt76.token_lock);
++}
++#endif
++
++int
++mt7915_pci_wed_init(struct mt7915_dev *dev, struct device *pdev, int *irq)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ struct mt76_dev *mdev = &dev->mt76;
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++ u32 base;
++ int ret;
++
++ if (!wed_enable)
++ return 0;
++
++ if (dev_is_pci(pdev)) {
++ struct pci_dev *pci_dev;
++
++ pci_dev = container_of(pdev, struct pci_dev, dev);
++ base = pci_resource_start(pci_dev, 0);
++ wed->wlan.base = (void __iomem *)ioremap(base, pci_resource_len(pci_dev, 0));
++
++ wed->wlan.pci_dev = pci_dev;
++ wed->wlan.bus_type = MTK_BUS_TYPE_PCIE;
++ wed->wlan.wpdma_int = base + MT_INT_WED_SOURCE_CSR;
++ wed->wlan.wpdma_mask = base + MT_INT_WED_MASK_CSR;
++ } else {
++ struct platform_device *plat_dev;
++ struct resource *res;
++
++ plat_dev = to_platform_device(pdev);
++ res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
++ base = res->start;
++ wed->wlan.base = (void __iomem *)ioremap(base, resource_size(res));
++ wed->wlan.bus_type = MTK_BUS_TYPE_AXI;
++ wed->wlan.wpdma_int = base + MT_INT_SOURCE_CSR;
++ wed->wlan.wpdma_mask = base + MT_INT_MASK_CSR;
++ }
++ wed->wlan.wpdma_tx = base + MT_TXQ_WED_RING_BASE;
++ wed->wlan.wpdma_txfree = base + MT_RXQ_WED_RING_BASE;
++
++ wed->wlan.tx_tbit[0] = MT_WED_TX_DONE_BAND0;
++ wed->wlan.tx_tbit[1] = MT_WED_TX_DONE_BAND1;
++ wed->wlan.txfree_tbit = MT_WED_TX_FREE_DONE;
++ wed->wlan.nbuf = 7168;
++ wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
++ wed->wlan.init_buf = mt7915_wed_init_buf;
++ /* disable dynamic tx token */
++ wed->wlan.offload_enable = mt7915_wed_offload_enable;
++ wed->wlan.offload_disable = mt7915_wed_offload_disable;
++
++ if (mtk_wed_device_attach(wed) != 0)
++ return 0;
++
++ if (wed->ver == MTK_WED_V1)
++ wed->wlan.wpdma_phys = base + MT_WFDMA_EXT_CSR_BASE;
++
++ *irq = wed->irq;
++ dev->mt76.dma_dev = wed->dev;
++ mdev->token_size = wed->wlan.token_start;
++ ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
++ if (ret)
++ return ret;
++
++ return 1;
++#else
++ return 0;
++#endif
++}
++
+ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
+ void __iomem *mem_base, u32 device_id)
+ {
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 62350141..d7a2e594 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -522,6 +522,8 @@ static inline void mt7986_wmac_disable(struct mt7915_dev *dev)
+ {
+ }
+ #endif
++int mt7915_pci_wed_init(struct mt7915_dev *dev,
++ struct device *pdev, int *irq);
+ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
+ void __iomem *mem_base, u32 device_id);
+ void mt7915_wfsys_reset(struct mt7915_dev *dev);
+diff --git a/mt7915/pci.c b/mt7915/pci.c
+index d74f6097..c5da01a9 100644
+--- a/mt7915/pci.c
++++ b/mt7915/pci.c
+@@ -12,9 +12,6 @@
+ #include "mac.h"
+ #include "../trace.h"
+
+-static bool wed_enable = false;
+-module_param(wed_enable, bool, 0644);
+-
+ static LIST_HEAD(hif_list);
+ static DEFINE_SPINLOCK(hif_lock);
+ static u32 hif_idx;
+@@ -95,73 +92,6 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+-static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
+-{
+- struct mt7915_dev *dev;
+- int ret;
+-
+- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+-
+- spin_lock_bh(&dev->mt76.token_lock);
+- dev->mt76.token_size = wed->wlan.token_start;
+- spin_unlock_bh(&dev->mt76.token_lock);
+-
+- ret = wait_event_timeout(dev->mt76.tx_wait,
+- !dev->mt76.wed_token_count, HZ);
+- if (!ret)
+- return -EAGAIN;
+-
+- return 0;
+-}
+-
+-static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
+-{
+- struct mt7915_dev *dev;
+-
+- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+-
+- spin_lock_bh(&dev->mt76.token_lock);
+- dev->mt76.token_size = MT7915_TOKEN_SIZE;
+- spin_unlock_bh(&dev->mt76.token_lock);
+-}
+-#endif
+-
+-static int
+-mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
+-{
+-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+- int ret;
+-
+- if (!wed_enable)
+- return 0;
+-
+- wed->wlan.pci_dev = pdev;
+- wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
+- MT_WFDMA_EXT_CSR_BASE;
+- wed->wlan.nbuf = 4096;
+- wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
+- wed->wlan.init_buf = mt7915_wed_init_buf;
+- wed->wlan.offload_enable = mt7915_wed_offload_enable;
+- wed->wlan.offload_disable = mt7915_wed_offload_disable;
+-
+- if (mtk_wed_device_attach(wed) != 0)
+- return 0;
+-
+- *irq = wed->irq;
+- dev->mt76.dma_dev = wed->dev;
+-
+- ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
+- if (ret)
+- return ret;
+-
+- return 1;
+-#else
+- return 0;
+-#endif
+-}
+-
+ static int mt7915_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+@@ -199,7 +129,7 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
+ mt7915_wfsys_reset(dev);
+ hif2 = mt7915_pci_init_hif2(pdev);
+
+- ret = mt7915_pci_wed_init(dev, pdev, &irq);
++ ret = mt7915_pci_wed_init(dev, &pdev->dev, &irq);
+ if (ret < 0)
+ goto free_wed_or_irq_vector;
+
+diff --git a/mt7915/regs.h b/mt7915/regs.h
+index 444440e1..ffda5f6b 100644
+--- a/mt7915/regs.h
++++ b/mt7915/regs.h
+@@ -623,6 +623,7 @@ enum offs_rev {
+ #define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
+ #define MT_PCIE_RECOG_ID_SEM BIT(31)
+
++#define MT_INT_WED_SOURCE_CSR MT_WFDMA_EXT_CSR(0x200)
+ #define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204)
+
+ #define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300)
+@@ -669,6 +670,13 @@ enum offs_rev {
+ #define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
+ MT_TXQ_ID(q)* 0x4)
+
++#define MT_TXQ_WED_RING_BASE (!is_mt7986(mdev)? 0xd7300 : 0x24420)
++#define MT_RXQ_WED_RING_BASE (!is_mt7986(mdev)? 0xd7410 : 0x24520)
++
++#define MT_WED_TX_DONE_BAND0 (is_mt7915(mdev)? 4 : 30)
++#define MT_WED_TX_DONE_BAND1 (is_mt7915(mdev)? 5 : 31)
++#define MT_WED_TX_FREE_DONE (is_mt7915(mdev)? 1 : 2)
++
+ #define MT_INT_SOURCE_CSR __REG(INT_SOURCE_CSR)
+ #define MT_INT_MASK_CSR __REG(INT_MASK_CSR)
+
+@@ -687,6 +695,11 @@ enum offs_rev {
+ #define MT_INT_RX_DONE_WA_MAIN_MT7916 BIT(2)
+ #define MT_INT_RX_DONE_WA_EXT_MT7916 BIT(3)
+
++#define MT_INT_WED_RX_DONE_BAND0_MT7916 BIT(18)
++#define MT_INT_WED_RX_DONE_BAND1_MT7916 BIT(19)
++#define MT_INT_WED_RX_DONE_WA_MAIN_MT7916 BIT(1)
++#define MT_INT_WED_RX_DONE_WA_MT7916 BIT(17)
++
+ #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
+ #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
+
+@@ -710,6 +723,8 @@ enum offs_rev {
+ #define MT_INT_TX_DONE_BAND0 BIT(30)
+ #define MT_INT_TX_DONE_BAND1 BIT(31)
+ #define MT_INT_TX_DONE_MCU_WA_MT7916 BIT(25)
++#define MT_INT_WED_TX_DONE_BAND0 BIT(4)
++#define MT_INT_WED_TX_DONE_BAND1 BIT(5)
+
+ #define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \
+ MT_INT_TX_MCU(MT_MCUQ_WM) | \
+diff --git a/mt7915/soc.c b/mt7915/soc.c
+index 3618718d..8d0b2068 100644
+--- a/mt7915/soc.c
++++ b/mt7915/soc.c
+@@ -1171,10 +1171,6 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
+
+ chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
+
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0)
+- return irq;
+-
+ mem_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mem_base)) {
+ dev_err(&pdev->dev, "Failed to get memory resource\n");
+@@ -1186,6 +1182,16 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
+ return PTR_ERR(dev);
+
+ mdev = &dev->mt76;
++ ret = mt7915_pci_wed_init(dev, &pdev->dev, &irq);
++ if (ret < 0)
++ goto free_device;
++
++ if (!ret) {
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return irq;;
++ }
++
+ ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret)
+@@ -1207,6 +1213,8 @@ free_irq:
+ devm_free_irq(mdev->dev, irq, dev);
+
+ free_device:
++ if (mtk_wed_device_active(&mdev->mmio.wed))
++ mtk_wed_device_detach(&mdev->mmio.wed);
+ mt76_free_device(&dev->mt76);
+
+ return ret;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
new file mode 100755
index 0000000..5c5a05d
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
@@ -0,0 +1,1152 @@
+From 1abac441c94f3f32bd074b8b01c439263129102d Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Tue, 5 Jul 2022 19:42:55 +0800
+Subject: [PATCH 2/3] mt76 add wed rx support
+
+Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
+---
+ dma.c | 219 +++++++++++++++++++++++++++++++++--------
+ dma.h | 10 ++
+ mac80211.c | 8 +-
+ mt76.h | 24 ++++-
+ mt7603/dma.c | 2 +-
+ mt7603/mt7603.h | 2 +-
+ mt7615/mac.c | 2 +-
+ mt7615/mt7615.h | 2 +-
+ mt76_connac_mcu.c | 9 ++
+ mt76x02.h | 2 +-
+ mt76x02_txrx.c | 2 +-
+ mt7915/dma.c | 10 ++
+ mt7915/mac.c | 89 ++++++++++++++++-
+ mt7915/mcu.c | 3 +
+ mt7915/mmio.c | 26 ++++-
+ mt7915/mt7915.h | 7 +-
+ mt7915/regs.h | 14 ++-
+ mt7921/mac.c | 2 +-
+ mt7921/mt7921.h | 4 +-
+ mt7921/pci_mac.c | 4 +-
+ tx.c | 34 +++++++
+ 21 files changed, 410 insertions(+), 65 deletions(-)
+ mode change 100755 => 100644 mt7915/mac.c
+ mode change 100755 => 100644 mt7915/mmio.c
+
+diff --git a/dma.c b/dma.c
+index 03ee910..094aede 100644
+--- a/dma.c
++++ b/dma.c
+@@ -98,6 +98,63 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
+ }
+ EXPORT_SYMBOL_GPL(mt76_put_txwi);
+
++static struct mt76_txwi_cache *
++mt76_alloc_rxwi(struct mt76_dev *dev)
++{
++ struct mt76_txwi_cache *r;
++ int size;
++
++ size = L1_CACHE_ALIGN(sizeof(*r));
++ r = kzalloc(size, GFP_ATOMIC);
++ if (!r)
++ return NULL;
++
++ r->buf = NULL;
++
++ return r;
++}
++
++static struct mt76_txwi_cache *
++__mt76_get_rxwi(struct mt76_dev *dev)
++{
++ struct mt76_txwi_cache *r = NULL;
++
++ spin_lock(&dev->wed_lock);
++ if (!list_empty(&dev->rxwi_cache)) {
++ r = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
++ list);
++ if(r)
++ list_del(&r->list);
++ }
++ spin_unlock(&dev->wed_lock);
++
++ return r;
++}
++
++struct mt76_txwi_cache *
++mt76_get_rxwi(struct mt76_dev *dev)
++{
++ struct mt76_txwi_cache *r = __mt76_get_rxwi(dev);
++
++ if (r)
++ return r;
++
++ return mt76_alloc_rxwi(dev);
++}
++EXPORT_SYMBOL_GPL(mt76_get_rxwi);
++
++void
++mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *r)
++{
++ if (!r)
++ return;
++
++ spin_lock(&dev->wed_lock);
++ list_add(&r->list, &dev->rxwi_cache);
++ spin_unlock(&dev->wed_lock);
++}
++EXPORT_SYMBOL_GPL(mt76_put_rxwi);
++
+ static void
+ mt76_free_pending_txwi(struct mt76_dev *dev)
+ {
+@@ -141,12 +198,15 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
+ static int
+ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ struct mt76_queue_buf *buf, int nbufs, u32 info,
+- struct sk_buff *skb, void *txwi)
++ struct sk_buff *skb, void *txwi, void *rxwi)
+ {
++ struct mtk_wed_device *wed = &dev->mmio.wed;
++
+ struct mt76_queue_entry *entry;
+ struct mt76_desc *desc;
+ u32 ctrl;
+ int i, idx = -1;
++ int type;
+
+ if (txwi) {
+ q->entry[q->head].txwi = DMA_DUMMY_DATA;
+@@ -162,28 +222,42 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ desc = &q->desc[idx];
+ entry = &q->entry[idx];
+
+- if (buf[0].skip_unmap)
+- entry->skip_buf0 = true;
+- entry->skip_buf1 = i == nbufs - 1;
+-
+- entry->dma_addr[0] = buf[0].addr;
+- entry->dma_len[0] = buf[0].len;
+-
+- ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+- if (i < nbufs - 1) {
+- entry->dma_addr[1] = buf[1].addr;
+- entry->dma_len[1] = buf[1].len;
+- buf1 = buf[1].addr;
+- ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
+- if (buf[1].skip_unmap)
+- entry->skip_buf1 = true;
++ type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
++ if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) {
++ struct mt76_txwi_cache *r = rxwi;
++ int rx_token;
++
++ if (!r)
++ return -ENOMEM;
++
++ rx_token = mt76_rx_token_consume(dev, (void *)skb, r, buf[0].addr);
++
++ buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
++ ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, MTK_WED_RX_PKT_SIZE);
++ ctrl |= MT_DMA_CTL_TO_HOST;
++ } else {
++ if (buf[0].skip_unmap)
++ entry->skip_buf0 = true;
++ entry->skip_buf1 = i == nbufs - 1;
++
++ entry->dma_addr[0] = buf[0].addr;
++ entry->dma_len[0] = buf[0].len;
++
++ ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
++ if (i < nbufs - 1) {
++ entry->dma_addr[1] = buf[1].addr;
++ entry->dma_len[1] = buf[1].len;
++ buf1 = buf[1].addr;
++ ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
++ if (buf[1].skip_unmap)
++ entry->skip_buf1 = true;
++ }
++ if (i == nbufs - 1)
++ ctrl |= MT_DMA_CTL_LAST_SEC0;
++ else if (i == nbufs - 2)
++ ctrl |= MT_DMA_CTL_LAST_SEC1;
+ }
+
+- if (i == nbufs - 1)
+- ctrl |= MT_DMA_CTL_LAST_SEC0;
+- else if (i == nbufs - 2)
+- ctrl |= MT_DMA_CTL_LAST_SEC1;
+-
+ WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
+ WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+ WRITE_ONCE(desc->info, cpu_to_le32(info));
+@@ -272,33 +346,63 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+
+ static void *
+ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+- int *len, u32 *info, bool *more)
++ int *len, u32 *info, bool *more, bool *drop)
+ {
+ struct mt76_queue_entry *e = &q->entry[idx];
+ struct mt76_desc *desc = &q->desc[idx];
+ dma_addr_t buf_addr;
+ void *buf = e->buf;
+ int buf_len = SKB_WITH_OVERHEAD(q->buf_size);
++ struct mtk_wed_device *wed = &dev->mmio.wed;
++ int type;
+
+- buf_addr = e->dma_addr[0];
+ if (len) {
+ u32 ctl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ *len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctl);
+ *more = !(ctl & MT_DMA_CTL_LAST_SEC0);
+ }
+
+- if (info)
+- *info = le32_to_cpu(desc->info);
++ type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
++ if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) {
++ u32 token;
++ struct mt76_txwi_cache *r;
++
++ token = FIELD_GET(MT_DMA_CTL_TOKEN, desc->buf1);
++
++ r = mt76_rx_token_release(dev, token);
++ if (!r)
++ return NULL;
++
++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ if (!buf)
++ return NULL;
++
++ memcpy(buf, r->buf, MTK_WED_RX_PKT_SIZE);
++ buf_addr = r->dma_addr;
++ buf_len = MTK_WED_RX_PKT_SIZE;
++ r->dma_addr = 0;
++ //r->buf = NULL;
++
++ mt76_put_rxwi(dev, r);
++
++ if (desc->ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP))
++ *drop = true;
++ } else {
++ buf_addr = e->dma_addr[0];
++ e->buf = NULL;
++ }
+
+ dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE);
+- e->buf = NULL;
++
++ if (info)
++ *info = le32_to_cpu(desc->info);
+
+ return buf;
+ }
+
+ static void *
+ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+- int *len, u32 *info, bool *more)
++ int *len, u32 *info, bool *more, bool *drop)
+ {
+ int idx = q->tail;
+
+@@ -314,7 +418,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+ q->tail = (q->tail + 1) % q->ndesc;
+ q->queued--;
+
+- return mt76_dma_get_buf(dev, q, idx, len, info, more);
++ return mt76_dma_get_buf(dev, q, idx, len, info, more, drop);
+ }
+
+ static int
+@@ -336,7 +440,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+ buf.len = skb->len;
+
+ spin_lock_bh(&q->lock);
+- mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
++ mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL, NULL);
+ mt76_dma_kick_queue(dev, q);
+ spin_unlock_bh(&q->lock);
+
+@@ -413,7 +517,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ goto unmap;
+
+ return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
+- tx_info.info, tx_info.skb, t);
++ tx_info.info, tx_info.skb, t, NULL);
+
+ unmap:
+ for (n--; n > 0; n--)
+@@ -448,6 +552,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ int frames = 0;
+ int len = SKB_WITH_OVERHEAD(q->buf_size);
+ int offset = q->buf_offset;
++ struct mtk_wed_device *wed = &dev->mmio.wed;
+
+ if (!q->ndesc)
+ return 0;
+@@ -456,10 +561,27 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+
+ while (q->queued < q->ndesc - 1) {
+ struct mt76_queue_buf qbuf;
++ int type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
++ bool skip_alloc = false;
++ struct mt76_txwi_cache *r = NULL;
++
++ if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) {
++ r = mt76_get_rxwi(dev);
++ if (!r)
++ return -ENOMEM;
++
++ if (r->buf) {
++ skip_alloc = true;
++ len = MTK_WED_RX_PKT_SIZE;
++ buf = r->buf;
++ }
++ }
+
+- buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
+- if (!buf)
+- break;
++ if (!skip_alloc) {
++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ if (!buf)
++ break;
++ }
+
+ addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
+@@ -470,7 +592,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ qbuf.addr = addr + offset;
+ qbuf.len = len - offset;
+ qbuf.skip_unmap = false;
+- mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, NULL);
++ mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, NULL, r);
+ frames++;
+ }
+
+@@ -516,6 +638,11 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
+ if (!ret)
+ q->wed_regs = wed->txfree_ring.reg_base;
+ break;
++ case MT76_WED_Q_RX:
++ ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs);
++ if (!ret)
++ q->wed_regs = wed->rx_ring[ring].reg_base;
++ break;
+ default:
+ ret = -EINVAL;
+ }
+@@ -531,7 +658,8 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc, int bufsize,
+ u32 ring_base)
+ {
+- int ret, size;
++ int ret, size, type;
++ struct mtk_wed_device *wed = &dev->mmio.wed;
+
+ spin_lock_init(&q->lock);
+ spin_lock_init(&q->cleanup_lock);
+@@ -541,6 +669,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ q->buf_size = bufsize;
+ q->hw_idx = idx;
+
++ type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
++ if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX)
++ q->buf_size = SKB_DATA_ALIGN(NET_SKB_PAD + MTK_WED_RX_PKT_SIZE) +
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
++
+ size = q->ndesc * sizeof(struct mt76_desc);
+ q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
+ if (!q->desc)
+@@ -573,7 +706,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+
+ spin_lock_bh(&q->lock);
+ do {
+- buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more);
++ buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
+ if (!buf)
+ break;
+
+@@ -614,7 +747,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+
+ static void
+ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+- int len, bool more)
++ int len, bool more, u32 info)
+ {
+ struct sk_buff *skb = q->rx_head;
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+@@ -634,7 +767,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+
+ q->rx_head = NULL;
+ if (nr_frags < ARRAY_SIZE(shinfo->frags))
+- dev->drv->rx_skb(dev, q - dev->q_rx, skb);
++ dev->drv->rx_skb(dev, q - dev->q_rx, skb, info);
+ else
+ dev_kfree_skb(skb);
+ }
+@@ -655,6 +788,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ }
+
+ while (done < budget) {
++ bool drop = false;
+ u32 info;
+
+ if (check_ddone) {
+@@ -665,10 +799,13 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ break;
+ }
+
+- data = mt76_dma_dequeue(dev, q, false, &len, &info, &more);
++ data = mt76_dma_dequeue(dev, q, false, &len, &info, &more, &drop);
+ if (!data)
+ break;
+
++ if (drop)
++ goto free_frag;
++
+ if (q->rx_head)
+ data_len = q->buf_size;
+ else
+@@ -681,7 +818,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ }
+
+ if (q->rx_head) {
+- mt76_add_fragment(dev, q, data, len, more);
++ mt76_add_fragment(dev, q, data, len, more, info);
+ continue;
+ }
+
+@@ -708,7 +845,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ continue;
+ }
+
+- dev->drv->rx_skb(dev, q - dev->q_rx, skb);
++ dev->drv->rx_skb(dev, q - dev->q_rx, skb, info);
+ continue;
+
+ free_frag:
+diff --git a/dma.h b/dma.h
+index fdf786f..90370d1 100644
+--- a/dma.h
++++ b/dma.h
+@@ -16,6 +16,16 @@
+ #define MT_DMA_CTL_LAST_SEC0 BIT(30)
+ #define MT_DMA_CTL_DMA_DONE BIT(31)
+
++#define MT_DMA_CTL_TO_HOST BIT(8)
++#define MT_DMA_CTL_TO_HOST_A BIT(12)
++#define MT_DMA_CTL_DROP BIT(14)
++
++#define MT_DMA_CTL_TOKEN GENMASK(31, 16)
++
++#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
++#define MT_DMA_PPE_ENTRY GENMASK(30, 16)
++#define MT_DMA_INFO_PPE_VLD BIT(31)
++
+ #define MT_DMA_HDR_LEN 4
+ #define MT_RX_INFO_LEN 4
+ #define MT_FCE_INFO_LEN 4
+diff --git a/mac80211.c b/mac80211.c
+index af2c09a..fa5ce6e 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -594,11 +594,14 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ BIT(NL80211_IFTYPE_ADHOC);
+
+ spin_lock_init(&dev->token_lock);
++ spin_lock_init(&dev->rx_token_lock);
+ idr_init(&dev->token);
++ idr_init(&dev->rx_token);
+
+ INIT_LIST_HEAD(&dev->wcid_list);
+
+ INIT_LIST_HEAD(&dev->txwi_cache);
++ INIT_LIST_HEAD(&dev->rxwi_cache);
+ dev->token_size = dev->drv->token_size;
+
+ for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
+@@ -1296,7 +1299,10 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
+
+ while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
+ mt76_check_sta(dev, skb);
+- mt76_rx_aggr_reorder(skb, &frames);
++ if (mtk_wed_device_active(&dev->mmio.wed))
++ __skb_queue_tail(&frames, skb);
++ else
++ mt76_rx_aggr_reorder(skb, &frames);
+ }
+
+ mt76_rx_complete(dev, &frames, napi);
+diff --git a/mt76.h b/mt76.h
+index 4c8a671..24e4741 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -20,6 +20,8 @@
+
+ #define MT_MCU_RING_SIZE 32
+ #define MT_RX_BUF_SIZE 2048
++#define MTK_WED_RX_PKT_SIZE 1700
++
+ #define MT_SKB_HEAD_LEN 256
+
+ #define MT_MAX_NON_AQL_PKT 16
+@@ -35,6 +37,7 @@
+ FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
+ FIELD_PREP(MT_QFLAG_WED_RING, _n))
+ #define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
++#define MT_WED_Q_RX(_n) __MT_WED_Q(MT76_WED_Q_RX, _n)
+ #define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
+
+ struct mt76_dev;
+@@ -56,6 +59,7 @@ enum mt76_bus_type {
+ enum mt76_wed_type {
+ MT76_WED_Q_TX,
+ MT76_WED_Q_TXFREE,
++ MT76_WED_Q_RX,
+ };
+
+ struct mt76_bus_ops {
+@@ -305,7 +309,10 @@ struct mt76_txwi_cache {
+ struct list_head list;
+ dma_addr_t dma_addr;
+
+- struct sk_buff *skb;
++ union {
++ void *buf;
++ struct sk_buff *skb;
++ };
+ };
+
+ struct mt76_rx_tid {
+@@ -403,7 +410,7 @@ struct mt76_driver_ops {
+ bool (*rx_check)(struct mt76_dev *dev, void *data, int len);
+
+ void (*rx_skb)(struct mt76_dev *dev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+
+ void (*rx_poll_complete)(struct mt76_dev *dev, enum mt76_rxq_id q);
+
+@@ -747,6 +754,7 @@ struct mt76_dev {
+ struct ieee80211_hw *hw;
+
+ spinlock_t lock;
++ spinlock_t wed_lock;
+ spinlock_t cc_lock;
+
+ u32 cur_cc_bss_rx;
+@@ -772,6 +780,7 @@ struct mt76_dev {
+ struct sk_buff_head rx_skb[__MT_RXQ_MAX];
+
+ struct list_head txwi_cache;
++ struct list_head rxwi_cache;
+ struct mt76_queue *q_mcu[__MT_MCUQ_MAX];
+ struct mt76_queue q_rx[__MT_RXQ_MAX];
+ const struct mt76_queue_ops *queue_ops;
+@@ -785,6 +794,9 @@ struct mt76_dev {
+ u16 wed_token_count;
+ u16 token_count;
+ u16 token_size;
++ u16 rx_token_size;
++ spinlock_t rx_token_lock;
++ struct idr rx_token;
+
+ wait_queue_head_t tx_wait;
+ /* spinclock used to protect wcid pktid linked list */
+@@ -1351,6 +1363,8 @@ mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
+ }
+
+ void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
++void mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
++struct mt76_txwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
+ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
+ struct napi_struct *napi);
+ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
+@@ -1495,6 +1509,12 @@ struct mt76_txwi_cache *
+ mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
+ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
+ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
++int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
++ struct mt76_txwi_cache *r, dma_addr_t phys);
++void skb_trace(const struct sk_buff *skb, bool full_pkt);
++
++struct mt76_txwi_cache *
++mt76_rx_token_release(struct mt76_dev *dev, int token);
+
+ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
+ {
+diff --git a/mt7603/dma.c b/mt7603/dma.c
+index 590cff9..2ff71c5 100644
+--- a/mt7603/dma.c
++++ b/mt7603/dma.c
+@@ -69,7 +69,7 @@ free:
+ }
+
+ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+diff --git a/mt7603/mt7603.h b/mt7603/mt7603.h
+index 0fd46d9..f2ce22a 100644
+--- a/mt7603/mt7603.h
++++ b/mt7603/mt7603.h
+@@ -244,7 +244,7 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
+
+ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
+ void mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
+ int mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+diff --git a/mt7615/mac.c b/mt7615/mac.c
+index 3728627..14cdd9a 100644
+--- a/mt7615/mac.c
++++ b/mt7615/mac.c
+@@ -1648,7 +1648,7 @@ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)
+ EXPORT_SYMBOL_GPL(mt7615_rx_check);
+
+ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+diff --git a/mt7615/mt7615.h b/mt7615/mt7615.h
+index 25880d1..983469c 100644
+--- a/mt7615/mt7615.h
++++ b/mt7615/mt7615.h
+@@ -511,7 +511,7 @@ void mt7615_tx_worker(struct mt76_worker *w);
+ void mt7615_tx_token_put(struct mt7615_dev *dev);
+ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len);
+ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
+ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index cd35068..f90a08f 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -1190,6 +1190,7 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ int cmd, bool enable, bool tx)
+ {
+ struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
++ struct mtk_wed_device *wed = &dev->mmio.wed;
+ struct wtbl_req_hdr *wtbl_hdr;
+ struct tlv *sta_wtbl;
+ struct sk_buff *skb;
+@@ -1210,6 +1211,8 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ mt76_connac_mcu_wtbl_ba_tlv(dev, skb, params, enable, tx, sta_wtbl,
+ wtbl_hdr);
+
++ if (mtk_wed_device_active(wed) && wed->ver > MTK_WED_V1)
++ mtk_wed_device_update_msg(wed, WED_WO_STA_REC, skb->data, skb->len);
+ ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);
+ if (ret)
+ return ret;
+@@ -1220,6 +1223,8 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+
+ mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);
+
++ if (mtk_wed_device_active(wed) && wed->ver > MTK_WED_V1)
++ mtk_wed_device_update_msg(wed, WED_WO_STA_REC, skb->data, skb->len);
+ return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
+ }
+ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba);
+@@ -2634,6 +2639,7 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ struct mt76_wcid *wcid, enum set_key_cmd cmd)
+ {
+ struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
++ struct mtk_wed_device *wed = &dev->mmio.wed;
+ struct sk_buff *skb;
+ int ret;
+
+@@ -2645,6 +2651,9 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ if (ret)
+ return ret;
+
++ if (mtk_wed_device_active(wed) && wed->ver > MTK_WED_V1)
++ mtk_wed_device_update_msg(wed, WED_WO_STA_REC, skb->data, skb->len);
++
+ return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
+ }
+ EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_key);
+diff --git a/mt76x02.h b/mt76x02.h
+index f76fd22..0b872af 100644
+--- a/mt76x02.h
++++ b/mt76x02.h
+@@ -173,7 +173,7 @@ int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
+ void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
+ bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
+ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
+ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance);
+ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+diff --git a/mt76x02_txrx.c b/mt76x02_txrx.c
+index 96fdf42..bf24d3e 100644
+--- a/mt76x02_txrx.c
++++ b/mt76x02_txrx.c
+@@ -33,7 +33,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+ EXPORT_SYMBOL_GPL(mt76x02_tx);
+
+ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+ void *rxwi = skb->data;
+diff --git a/mt7915/dma.c b/mt7915/dma.c
+index 7122322..ac98e01 100644
+--- a/mt7915/dma.c
++++ b/mt7915/dma.c
+@@ -376,6 +376,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
++ mt76_rmw(dev, MT_WFDMA0_EXT0_CFG, MT_WFDMA0_EXT0_RXWB_KEEP,
++ MT_WFDMA0_EXT0_RXWB_KEEP);
+ } else {
+ mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
+@@ -451,6 +453,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+
+ /* rx data queue for band0 */
+ if (!dev->phy.band_idx) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++ dev->mt76.mmio.wed.ver > MTK_WED_V1)
++ dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(MT7915_RXQ_BAND0);
++
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
+ MT_RXQ_ID(MT_RXQ_MAIN),
+ MT7915_RX_RING_SIZE,
+@@ -482,6 +488,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+
+ if (dev->dbdc_support || dev->phy.band_idx) {
+ /* rx data queue for band1 */
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++ dev->mt76.mmio.wed.ver > MTK_WED_V1)
++ dev->mt76.q_rx[MT_RXQ_EXT].flags = MT_WED_Q_RX(MT7915_RXQ_BAND1);
++
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
+ MT_RXQ_ID(MT_RXQ_EXT),
+ MT7915_RX_RING_SIZE,
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+old mode 100755
+new mode 100644
+index bc8da4d..79b7d01
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -217,7 +217,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
+ }
+
+ static int
+-mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
++mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, enum mt76_rxq_id q, u32 info)
+ {
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ struct mt76_phy *mphy = &dev->mt76.phy;
+@@ -494,6 +494,27 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
+ #endif
+ } else {
+ status->flag |= RX_FLAG_8023;
++ if (msta || msta->vif) {
++ struct mtk_wed_device *wed;
++ int type;
++
++ wed = &dev->mt76.mmio.wed;
++ type = FIELD_GET(MT_QFLAG_WED_TYPE, dev->mt76.q_rx[q].flags);
++ if ((mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) &&
++ (info & MT_DMA_INFO_PPE_VLD)){
++ struct ieee80211_vif *vif;
++ u32 hash, reason;
++
++ vif = container_of((void *)msta->vif, struct ieee80211_vif,
++ drv_priv);
++
++ skb->dev = ieee80211_vif_to_netdev(vif);
++ reason = FIELD_GET(MT_DMA_PPE_CPU_REASON, info);
++ hash = FIELD_GET(MT_DMA_PPE_ENTRY, info);
++
++ mtk_wed_device_ppe_check(wed, skb, reason, hash);
++ }
++ }
+ }
+
+ if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
+@@ -840,6 +861,68 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+ return MT_TXD_TXP_BUF_SIZE;
+ }
+
++u32
++mt7915_wed_init_rx_buf(struct mtk_wed_device *wed, int pkt_num)
++{
++ struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
++ struct mt7915_dev *dev;
++ dma_addr_t buf_phys;
++ void *buf;
++ int i, token, buf_size;
++
++ buf_size = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_pkt_size) +
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
++
++ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
++ for (i = 0; i < pkt_num; i++) {
++ struct mt76_txwi_cache *r = mt76_get_rxwi(&dev->mt76);
++
++ buf = page_frag_alloc(&wed->rx_page, buf_size, GFP_ATOMIC);
++ if (!buf)
++ return -ENOMEM;
++
++ buf_phys = dma_map_single(dev->mt76.dma_dev, buf, wed->wlan.rx_pkt_size,
++ DMA_TO_DEVICE);
++
++ if (unlikely(dma_mapping_error(dev->mt76.dev, buf_phys))) {
++ skb_free_frag(buf);
++ break;
++ }
++
++ desc->buf0 = buf_phys;
++
++ token = mt76_rx_token_consume(&dev->mt76, buf, r, buf_phys);
++
++ desc->token |= FIELD_PREP(MT_DMA_CTL_TOKEN, token);
++ desc++;
++ }
++
++ return 0;
++}
++
++void mt7915_wed_release_rx_buf(struct mtk_wed_device *wed)
++{
++ struct mt76_txwi_cache *rxwi;
++ struct mt7915_dev *dev;
++ int token;
++
++ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
++
++ for(token = 0; token < dev->mt76.rx_token_size; token++) {
++ rxwi = mt76_rx_token_release(&dev->mt76, token);
++ if(!rxwi)
++ continue;
++
++ dma_unmap_single(dev->mt76.dma_dev, rxwi->dma_addr,
++ wed->wlan.rx_pkt_size, DMA_FROM_DEVICE);
++ skb_free_frag(rxwi->buf);
++ rxwi->buf = NULL;
++
++ mt76_put_rxwi(&dev->mt76, rxwi);
++ }
++ return;
++}
++
+ static void
+ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+ {
+@@ -1120,7 +1203,7 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
+ }
+
+ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+@@ -1154,7 +1237,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ dev_kfree_skb(skb);
+ break;
+ case PKT_TYPE_NORMAL:
+- if (!mt7915_mac_fill_rx(dev, skb)) {
++ if (!mt7915_mac_fill_rx(dev, skb, q, info)) {
+ mt76_rx(&dev->mt76, q, skb);
+ return;
+ }
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 1468c3c..4f64df4 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -1704,6 +1704,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, bool enable)
+ {
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ struct mt7915_sta *msta;
+ struct sk_buff *skb;
+ int ret;
+@@ -1756,6 +1757,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ return ret;
+ }
+ out:
++ if (mtk_wed_device_active(wed) && wed->ver > MTK_WED_V1)
++ mtk_wed_device_update_msg(wed, WED_WO_STA_REC, skb->data, skb->len);
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_EXT_CMD(STA_REC_UPDATE), true);
+ }
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+old mode 100755
+new mode 100644
+index b4a3120..08ff556
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -28,6 +28,9 @@ static const u32 mt7915_reg[] = {
+ [FW_EXCEPTION_ADDR] = 0x219848,
+ [SWDEF_BASE_ADDR] = 0x41f200,
+ [EXCEPTION_BASE_ADDR] = 0x219848,
++ [WED_TX_RING] = 0xd7300,
++ [WED_RX_RING] = 0xd7410,
++ [WED_RX_DATA_RING] = 0xd4500,
+ };
+
+ static const u32 mt7916_reg[] = {
+@@ -45,6 +48,9 @@ static const u32 mt7916_reg[] = {
+ [FW_EXCEPTION_ADDR] = 0x022050bc,
+ [SWDEF_BASE_ADDR] = 0x411400,
+ [EXCEPTION_BASE_ADDR] = 0x022050BC,
++ [WED_TX_RING] = 0xd7300,
++ [WED_RX_RING] = 0xd7410,
++ [WED_RX_DATA_RING] = 0xd4540,
+ };
+
+ static const u32 mt7986_reg[] = {
+@@ -62,6 +68,9 @@ static const u32 mt7986_reg[] = {
+ [FW_EXCEPTION_ADDR] = 0x02204ffc,
+ [SWDEF_BASE_ADDR] = 0x411400,
+ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
++ [WED_TX_RING] = 0x24420,
++ [WED_RX_RING] = 0x24520,
++ [WED_RX_DATA_RING] = 0x24540,
+ };
+
+ static const u32 mt7915_offs[] = {
+@@ -710,6 +719,7 @@ mt7915_pci_wed_init(struct mt7915_dev *dev, struct device *pdev, int *irq)
+ wed->wlan.bus_type = MTK_BUS_TYPE_PCIE;
+ wed->wlan.wpdma_int = base + MT_INT_WED_SOURCE_CSR;
+ wed->wlan.wpdma_mask = base + MT_INT_WED_MASK_CSR;
++ wed->wlan.wpdma_phys = base + MT_WFDMA_EXT_CSR_BASE;
+ } else {
+ struct platform_device *plat_dev;
+ struct resource *res;
+@@ -722,12 +732,19 @@ mt7915_pci_wed_init(struct mt7915_dev *dev, struct device *pdev, int *irq)
+ wed->wlan.wpdma_int = base + MT_INT_SOURCE_CSR;
+ wed->wlan.wpdma_mask = base + MT_INT_MASK_CSR;
+ }
++ wed->wlan.rx_pkt = MT7915_WED_RX_TOKEN_SIZE;
++ wed->wlan.phy_base = base;
+ wed->wlan.wpdma_tx = base + MT_TXQ_WED_RING_BASE;
+ wed->wlan.wpdma_txfree = base + MT_RXQ_WED_RING_BASE;
++ wed->wlan.wpdma_rx_glo = base + MT_WPDMA_GLO_CFG;
++ wed->wlan.wpdma_rx = base + MT_RXQ_WED_DATA_RING_BASE;
+
+ wed->wlan.tx_tbit[0] = MT_WED_TX_DONE_BAND0;
+ wed->wlan.tx_tbit[1] = MT_WED_TX_DONE_BAND1;
+ wed->wlan.txfree_tbit = MT_WED_TX_FREE_DONE;
++ wed->wlan.rx_tbit[0] = MT_WED_RX_DONE_BAND0;
++ wed->wlan.rx_tbit[1] = MT_WED_RX_DONE_BAND1;
++
+ wed->wlan.nbuf = 7168;
+ wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
+ wed->wlan.init_buf = mt7915_wed_init_buf;
+@@ -735,12 +752,15 @@ mt7915_pci_wed_init(struct mt7915_dev *dev, struct device *pdev, int *irq)
+ wed->wlan.offload_enable = mt7915_wed_offload_enable;
+ wed->wlan.offload_disable = mt7915_wed_offload_disable;
+
++ wed->wlan.rx_nbuf = 65536;
++ wed->wlan.rx_pkt_size = MTK_WED_RX_PKT_SIZE;
++ wed->wlan.init_rx_buf = mt7915_wed_init_rx_buf;
++ wed->wlan.release_rx_buf = mt7915_wed_release_rx_buf;
++
++ dev->mt76.rx_token_size = wed->wlan.rx_pkt + MT7915_RX_RING_SIZE * 2;
+ if (mtk_wed_device_attach(wed) != 0)
+ return 0;
+
+- if (wed->ver == MTK_WED_V1)
+- wed->wlan.wpdma_phys = base + MT_WFDMA_EXT_CSR_BASE;
+-
+ *irq = wed->irq;
+ dev->mt76.dma_dev = wed->dev;
+ mdev->token_size = wed->wlan.token_start;
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index fe407c5..e2f0d41 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -69,6 +69,7 @@
+ #define MT7915_MAX_STA_TWT_AGRT 8
+ #define MT7915_MIN_TWT_DUR 64
+ #define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2)
++#define MT7915_WED_RX_TOKEN_SIZE 12288
+
+ struct mt7915_vif;
+ struct mt7915_sta;
+@@ -531,7 +532,9 @@ void mt7915_wfsys_reset(struct mt7915_dev *dev);
+ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance);
+ u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif);
+ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+-
++u32 mt7915_wed_init_rx_buf(struct mtk_wed_device *wed,
++ int pkt_num);
++void mt7915_wed_release_rx_buf(struct mtk_wed_device *wed);
+ int mt7915_register_device(struct mt7915_dev *dev);
+ void mt7915_unregister_device(struct mt7915_dev *dev);
+ int mt7915_eeprom_init(struct mt7915_dev *dev);
+@@ -683,7 +686,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct mt76_tx_info *tx_info);
+ void mt7915_tx_token_put(struct mt7915_dev *dev);
+ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
+ void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
+ void mt7915_stats_work(struct work_struct *work);
+diff --git a/mt7915/regs.h b/mt7915/regs.h
+index ffda5f6..08bf84c 100644
+--- a/mt7915/regs.h
++++ b/mt7915/regs.h
+@@ -33,6 +33,9 @@ enum reg_rev {
+ FW_EXCEPTION_ADDR,
+ SWDEF_BASE_ADDR,
+ EXCEPTION_BASE_ADDR,
++ WED_TX_RING,
++ WED_RX_RING,
++ WED_RX_DATA_RING,
+ __MT_REG_MAX,
+ };
+
+@@ -570,9 +573,13 @@ enum offs_rev {
+ #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
+
+ #define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
++#define MT_WFDMA0_EXT0_CFG MT_WFDMA0(0x2b0)
++#define MT_WFDMA0_EXT0_RXWB_KEEP BIT(10)
++
+ #define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
+ #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
+ #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
++#define MT_WPDMA_GLO_CFG MT_WFDMA0(0x208)
+
+ #define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
+ #define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
+@@ -670,12 +677,15 @@ enum offs_rev {
+ #define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
+ MT_TXQ_ID(q)* 0x4)
+
+-#define MT_TXQ_WED_RING_BASE (!is_mt7986(mdev)? 0xd7300 : 0x24420)
+-#define MT_RXQ_WED_RING_BASE (!is_mt7986(mdev)? 0xd7410 : 0x24520)
++#define MT_TXQ_WED_RING_BASE __REG(WED_TX_RING)
++#define MT_RXQ_WED_RING_BASE __REG(WED_RX_RING)
++#define MT_RXQ_WED_DATA_RING_BASE __REG(WED_RX_DATA_RING)
+
+ #define MT_WED_TX_DONE_BAND0 (is_mt7915(mdev)? 4 : 30)
+ #define MT_WED_TX_DONE_BAND1 (is_mt7915(mdev)? 5 : 31)
+ #define MT_WED_TX_FREE_DONE (is_mt7915(mdev)? 1 : 2)
++#define MT_WED_RX_DONE_BAND0 (is_mt7915(mdev)? 16 : 22)
++#define MT_WED_RX_DONE_BAND1 (is_mt7915(mdev)? 17 : 23)
+
+ #define MT_INT_SOURCE_CSR __REG(INT_SOURCE_CSR)
+ #define MT_INT_MASK_CSR __REG(INT_MASK_CSR)
+diff --git a/mt7921/mac.c b/mt7921/mac.c
+index 4fcadf8..4897940 100644
+--- a/mt7921/mac.c
++++ b/mt7921/mac.c
+@@ -555,7 +555,7 @@ out:
+ EXPORT_SYMBOL_GPL(mt7921_mac_add_txs);
+
+ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+diff --git a/mt7921/mt7921.h b/mt7921/mt7921.h
+index efeb82c..4b2e974 100644
+--- a/mt7921/mt7921.h
++++ b/mt7921/mt7921.h
+@@ -388,7 +388,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ void mt7921_tx_worker(struct mt76_worker *w);
+ void mt7921_tx_token_put(struct mt7921_dev *dev);
+ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
+ void mt7921_stats_work(struct work_struct *work);
+ void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
+@@ -424,7 +424,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
+
+ bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len);
+ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb);
++ struct sk_buff *skb, u32 info);
+ int mt7921e_driver_own(struct mt7921_dev *dev);
+ int mt7921e_mac_reset(struct mt7921_dev *dev);
+ int mt7921e_mcu_init(struct mt7921_dev *dev);
+diff --git a/mt7921/pci_mac.c b/mt7921/pci_mac.c
+index e180067..ca982eb 100644
+--- a/mt7921/pci_mac.c
++++ b/mt7921/pci_mac.c
+@@ -182,7 +182,7 @@ bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len)
+ }
+
+ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u32 info)
+ {
+ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+ __le32 *rxd = (__le32 *)skb->data;
+@@ -196,7 +196,7 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ napi_consume_skb(skb, 1);
+ break;
+ default:
+- mt7921_queue_rx_skb(mdev, q, skb);
++ mt7921_queue_rx_skb(mdev, q, skb, info);
+ break;
+ }
+ }
+diff --git a/tx.c b/tx.c
+index ae44afe..bccd206 100644
+--- a/tx.c
++++ b/tx.c
+@@ -767,3 +767,37 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
+ return txwi;
+ }
+ EXPORT_SYMBOL_GPL(mt76_token_release);
++
++int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
++ struct mt76_txwi_cache *r, dma_addr_t phys)
++{
++ int token;
++
++ spin_lock_bh(&dev->rx_token_lock);
++
++ token = idr_alloc(&dev->rx_token, r, 0, dev->rx_token_size, GFP_ATOMIC);
++
++ spin_unlock_bh(&dev->rx_token_lock);
++
++ r->buf = ptr;
++ r->dma_addr = phys;
++
++ return token;
++}
++EXPORT_SYMBOL_GPL(mt76_rx_token_consume);
++
++struct mt76_txwi_cache *
++mt76_rx_token_release(struct mt76_dev *dev, int token)
++{
++
++ struct mt76_txwi_cache *rxwi;
++
++ spin_lock_bh(&dev->rx_token_lock);
++
++ rxwi = idr_remove(&dev->rx_token, token);
++
++ spin_unlock_bh(&dev->rx_token_lock);
++
++ return rxwi;
++}
++EXPORT_SYMBOL_GPL(mt76_rx_token_release);
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/3003-mt76-add-fill-receive-path-to-report-wed-idx.patch b/recipes-kernel/linux-mt76/files/patches/3003-mt76-add-fill-receive-path-to-report-wed-idx.patch
new file mode 100755
index 0000000..3e3d8be
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/3003-mt76-add-fill-receive-path-to-report-wed-idx.patch
@@ -0,0 +1,49 @@
+From bad890a89e289efc57091c0c08bbfad701147e4e Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Thu, 19 May 2022 13:44:42 +0800
+Subject: [PATCH 3/3] add fill receive path to report wed idx
+
+Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
+---
+ mt7915/main.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/mt7915/main.c b/mt7915/main.c
+index f1396eed..a0798d46 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -1458,6 +1458,24 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
+
+ return 0;
+ }
++
++static int
++mt7915_net_fill_receive_path(struct ieee80211_hw *hw,
++ struct net_device_path_ctx *ctx,
++ struct net_device_path *path)
++{
++ struct mt7915_dev *dev = mt7915_hw_dev(hw);
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++
++ if (!mtk_wed_device_active(wed))
++ return -ENODEV;
++
++ path->dev = ctx->dev;
++ path->mtk_wdma.wdma_idx = wed->wdma_idx;
++
++ return 0;
++}
++
+ #endif
+
+ const struct ieee80211_ops mt7915_ops = {
+@@ -1509,5 +1527,6 @@ const struct ieee80211_ops mt7915_ops = {
+ .set_radar_background = mt7915_set_radar_background,
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ .net_fill_forward_path = mt7915_net_fill_forward_path,
++ .net_fill_receive_path = mt7915_net_fill_receive_path,
+ #endif
+ };
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/patches.inc b/recipes-kernel/linux-mt76/files/patches/patches.inc
index 868ea02..da26649 100644
--- a/recipes-kernel/linux-mt76/files/patches/patches.inc
+++ b/recipes-kernel/linux-mt76/files/patches/patches.inc
@@ -21,5 +21,8 @@
file://1113-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch \
file://1114-mt76-airtime-fairness-feature-off-in-mac80211.patch \
file://1115-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch \
- file://3000-mt76-remove-WED-support-patch-for-build-err.patch \
+ file://1116-mt76-mt7915-add-vendor-dump-phy-capa.patch \
+ file://3001-mt76-add-wed-tx-support.patch \
+ file://3002-mt76-add-wed-rx-support.patch \
+ file://3003-mt76-add-fill-receive-path-to-report-wed-idx.patch \
"