[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
cc3c51c7 [MAC80211][wifi6][Release][Update MT7986 Firmware]
ea393925 [MAC80211[WiFi6/7]][hostapd][Avoid unnecessary beacon update]
6763be22 [MAC80211][wifi7][Misc][Sync Internal patches to External Release Folder]
d3ed9bc8 [mac80211][wifi7][mt76][Rebase WED patch due to Cheetah MT76 modifications]
2f4b03c3 [mac80211][wifi6][mt76][Bring-up hardware path for Cheetah MT76]
cb573d78 [MAC80211][WiFi7][app][Add ibf atenl support for eagle]
04fe6893 [mac80211][wifi6][mt76][Fix rebase errors]
c301e69a [MAC80211][WiFi7][mt76][Update Kite EEPROM bin files]
463b00fb [MAC80211][WiFi7][infra][Add slot1 for kite]
8774388d [MAC80211][WiFi7][misc][Prevent deadlock in a multiple AP+STA mode]
68d43fea [MAC80211][hostapd][show acs channels config]
5aca83c6 [MAC80211][hostapd][Prevent hostapd from setting beacon too frequently]
636da369 [MAC80211][wifi6/7][misc][use current epoch date]
9eb3456f [MAC80211][hostapd][refactor AP/STA CSA handling flow]
5543f3d8 [MAC80211][WiFi6][mt76][Refactor assignment of STA BSS group]
c5631fc2 [mac80211][mt76][wifi6][Add debugfs knob for RTS threshold]
6a92a2d4 [mac80211][wifi6][mt76][Bring-up software path for Cheetah MT76]
bf66c519 [MAC80211][netifd][Remove unnecessary netifd patch]
2f141c75 [mac80211][mt76][wifi6/7][Fix build failed]
cf30db1e [mac80211[hostapd][wifi7][Fix build fial]
dc391fc0 [MAC80211][wifi6][Release][Update MT7986 Firmware]
71a7b95a [MAC80211][WiFi7][mt76][Add kite fw & eeprom to eagle codebase]
5a7bd025 [MAC80211][WiFi6][misc][Add mt7981 default eeprom bin]
e40da697 [MAC80211][WED][Fix reinsert wifi module cause memory leak issue]
0a22f8f4 [MAC80211][WiFi7][misc][fix mt7988-mt7996-mac980211 release build fail]
25f3fe1c [[Eagle][SQC3.0][BE19000][MT7996][E2][MT7976_MT7977][256][ePA][MT7988A][WiFi] [MAP][SnS][Muti-client][UES]Traffic stuck in Agent2 with invalid tid 8 found]
f59b5dad [MAC80211][WiFi6][mt76][Add additional chain signal info in station dump for merlin]
fada400d [MAC80211][WiFi6/7][mt76][Add HT40- capab when enable ACS]
98e273af [MAC80211][WiFi6/7][app][Add SKU_EN & RSSI ATTR in atenl]
aaa8eb14 [MAC80211][WiFi6][mt76][Add rssi & sku_en in testmode]
eda14aac [MAC80211][core][Remove wrong assignment on the variable "changed" when changing beacon]
000329aa [MAC80211][netifd][Move netifd patch for wifi7 used only]
57bfe0c7 [MAC80211][WiFi6][misc][fix build fail due to mt76 upgration]
fa29bb39 [MAC80211][wifi6/7][mt76][update mt76 Makefile]
56f497ec [MAC80211][netifd][not to cache previous config to avoid wifi down failure]
be9abd4d [MAC80211][WiFi6][misc][fix build fail due to netifd]
af71e303 [MAC80211][WiFi6][mt76][Fix inconsistent BSS group setting of STA for VoW]
3e42972a [MAC80211][WiFi6][mt76][Fix txpower bbp CR]
81a68c03 [MAC80211][wifi7][hostapd][rebase internal hostapd patches]
336300b7 [MAC80211][WiFi6/7][hostapd][MAX 48 mbss 6G 连线概率连不上 ]
6bebc554 [MAC80211][wifi7][core][update for backports v6.5]
19daecfd [MAC80211][wifi7][ucode][Bandwidth Synchronization in AP/STA Mode]
ddf64afb [MAC80211][mt76][add debug log in SER flow]
44611a77 [mac80211][wifi6][mt76][Enhance debug log]
[Release-log]
Change-Id: Ibf5e835de5563fff4101a77e81056f696286670b
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
new file mode 100644
index 0000000..bef1050
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
@@ -0,0 +1,44 @@
+From 455955959ceaabf80454570c2dfaa3128d524791 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 19 Sep 2023 11:21:23 +0800
+Subject: [PATCH 01/98] Revert "wifi: mt76: mt7996: fill txd by host driver"
+
+This reverts commit 325a0c4931990d553487024c4f76c776492bdcc2.
+---
+ mt7996/mac.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index c43839a..1a1e218 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -967,8 +967,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ return id;
+
+ pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
+- pid, qid, 0);
++ memset(txwi_ptr, 0, MT_TXD_SIZE);
++ /* Transmit non qos data by 802.11 header and need to fill txd by host*/
++ if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
++ mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
++ pid, qid, 0);
+
+ txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
+ for (i = 0; i < nbuf; i++) {
+@@ -977,8 +980,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ }
+ txp->fw.nbuf = nbuf;
+
+- txp->fw.flags =
+- cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD);
++ txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
++
++ if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
++ txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
+
+ if (!key)
+ txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
deleted file mode 100644
index 91d65d7..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 15d734c77b25451efdf3bb1bcd5e687bc429a852 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 10 Feb 2023 17:39:23 +0800
-Subject: [PATCH 01/11] wifi: mt76: mt7996: add eht rx rate support
-
-Add support to report eht rx rate.
-
-Change-Id: Iee067d891bd634a918c942c2ba90ae72cd40c538
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mac80211.c | 11 ++++++++---
- mt76.h | 18 ++++++++++++++----
- mt7996/mac.c | 9 +++++----
- 3 files changed, 27 insertions(+), 11 deletions(-)
-
-diff --git a/mac80211.c b/mac80211.c
-index 2c4a5290..467afef9 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -1067,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
- status->enc_flags = mstat.enc_flags;
- status->encoding = mstat.encoding;
- status->bw = mstat.bw;
-- status->he_ru = mstat.he_ru;
-- status->he_gi = mstat.he_gi;
-- status->he_dcm = mstat.he_dcm;
-+ if (status->encoding == RX_ENC_EHT) {
-+ status->eht.ru = mstat.eht.ru;
-+ status->eht.gi = mstat.eht.gi;
-+ } else {
-+ status->he_ru = mstat.he_ru;
-+ status->he_gi = mstat.he_gi;
-+ status->he_dcm = mstat.he_dcm;
-+ }
- status->rate_idx = mstat.rate_idx;
- status->nss = mstat.nss;
- status->band = mstat.band;
-diff --git a/mt76.h b/mt76.h
-index 8b4635e9..6b07b8fa 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -621,12 +621,22 @@ struct mt76_rx_status {
- u16 freq;
- u32 flag;
- u8 enc_flags;
-- u8 encoding:2, bw:3, he_ru:3;
-- u8 he_gi:2, he_dcm:1;
-+ u8 encoding:3, bw:4;
-+ union {
-+ struct {
-+ u8 he_ru:3;
-+ u8 he_gi:2;
-+ u8 he_dcm:1;
-+ };
-+ struct {
-+ u8 ru:4;
-+ u8 gi:2;
-+ } eht;
-+ };
-+
- u8 amsdu:1, first_amsdu:1, last_amsdu:1;
- u8 rate_idx;
-- u8 nss;
-- u8 band;
-+ u8 nss:5, band:3;
- s8 signal;
- u8 chains;
- s8 chain_signal[IEEE80211_MAX_CHAINS];
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 0d51090d..23cbfdde 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -580,11 +580,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
- case MT_PHY_TYPE_EHT_SU:
- case MT_PHY_TYPE_EHT_TRIG:
- case MT_PHY_TYPE_EHT_MU:
-- /* TODO: currently report rx rate with HE rate */
- status->nss = nss;
-- status->encoding = RX_ENC_HE;
-- bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
-- i = min_t(int, i & 0xf, 11);
-+ status->encoding = RX_ENC_EHT;
-+ i &= GENMASK(3, 0);
-+
-+ if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
-+ status->eht.gi = gi;
- break;
- default:
- return -EINVAL;
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch
deleted file mode 100644
index 8ab501f..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 83d30a89d61ee914b23d77256e993e9521de5cbc Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Wed, 15 Feb 2023 18:38:04 +0800
-Subject: [PATCH 02/11] wifi: mt76: mt7996: move radio ctrl commands to proper
- functions
-
-Move radio enable/disable commands into functions for configuring
-per-phy radio.
-
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/main.c | 11 ++++++-----
- 1 file changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/mt7996/main.c b/mt7996/main.c
-index f306e9c5..e7c97d2f 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -43,6 +43,10 @@ int mt7996_run(struct ieee80211_hw *hw)
- if (ret)
- goto out;
-
-+ ret = mt7996_mcu_set_radio_en(phy, true);
-+ if (ret)
-+ goto out;
-+
- ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);
- if (ret)
- goto out;
-@@ -82,6 +86,8 @@ static void mt7996_stop(struct ieee80211_hw *hw)
-
- mutex_lock(&dev->mt76.mutex);
-
-+ mt7996_mcu_set_radio_en(phy, false);
-+
- clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
-
- mutex_unlock(&dev->mt76.mutex);
-@@ -190,10 +196,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
- if (ret)
- goto out;
-
-- ret = mt7996_mcu_set_radio_en(phy, true);
-- if (ret)
-- goto out;
--
- dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
- phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
-
-@@ -253,7 +255,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
- phy->monitor_vif = NULL;
-
- mt7996_mcu_add_dev_info(phy, vif, false);
-- mt7996_mcu_set_radio_en(phy, false);
-
- rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
-
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-wed-sync-to-wed-upstream.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-wed-sync-to-wed-upstream.patch
new file mode 100644
index 0000000..25dfc5d
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-wed-sync-to-wed-upstream.patch
@@ -0,0 +1,2740 @@
+From 4709ca02ba0332508ac6885acbc779bdfac3f0be Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Fri, 6 Oct 2023 21:20:25 +0800
+Subject: [PATCH] wifi: mt76: wed: sync to wed upstream
+
+---
+ dma.c | 219 +++++++++++++++++++++++++++------------
+ dma.h | 12 +++
+ mac80211.c | 19 +++-
+ mmio.c | 97 +++++++++++++++++
+ mt76.h | 102 ++++++++++++++++--
+ mt7603/dma.c | 9 +-
+ mt7615/dma.c | 6 +-
+ mt76_connac.h | 3 +-
+ mt76_connac_mac.c | 5 +-
+ mt76x02_mmio.c | 5 +-
+ mt7915/dma.c | 18 ++--
+ mt7915/main.c | 16 +--
+ mt7915/mmio.c | 107 +------------------
+ mt7921/pci.c | 2 +-
+ mt7925/pci.c | 2 +-
+ mt7996/dma.c | 258 ++++++++++++++++++++++++++++++++++++++++++----
+ mt7996/init.c | 156 ++++++++++++++++++++++++++--
+ mt7996/mac.c | 72 +++++++++++--
+ mt7996/main.c | 42 ++++++++
+ mt7996/mcu.c | 13 ++-
+ mt7996/mmio.c | 208 +++++++++++++++++++++++++++++++++----
+ mt7996/mt7996.h | 67 +++++++++++-
+ mt7996/pci.c | 72 ++++++++++---
+ mt7996/regs.h | 65 +++++++++++-
+ 24 files changed, 1276 insertions(+), 299 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 643e18e..dd20271 100644
+--- a/dma.c
++++ b/dma.c
+@@ -9,11 +9,11 @@
+
+ #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+
+-#define Q_READ(_dev, _q, _field) ({ \
++#define Q_READ(_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, \
++ _val = mtk_wed_device_reg_read((_q)->wed, \
+ ((_q)->wed_regs + \
+ _offset)); \
+ else \
+@@ -21,10 +21,10 @@
+ _val; \
+ })
+
+-#define Q_WRITE(_dev, _q, _field, _val) do { \
++#define Q_WRITE(_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, \
++ mtk_wed_device_reg_write((_q)->wed, \
+ ((_q)->wed_regs + _offset), \
+ _val); \
+ else \
+@@ -33,8 +33,8 @@
+
+ #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(_q, _field) readl(&(_q)->regs->_field)
++#define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field)
+
+ #endif
+
+@@ -188,40 +188,63 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
+ static void
+ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+- Q_WRITE(dev, q, desc_base, q->desc_dma);
+- Q_WRITE(dev, q, ring_size, q->ndesc);
+- q->head = Q_READ(dev, q, dma_idx);
++ Q_WRITE(q, desc_base, q->desc_dma);
++ if (q->flags & MT_QFLAG_WED_RRO_EN)
++ Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
++ else
++ Q_WRITE(q, ring_size, q->ndesc);
++ q->head = Q_READ(q, dma_idx);
+ q->tail = q->head;
+ }
+
+ static void
+-mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
++__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
++ bool reset_idx)
+ {
+- int i;
+-
+ if (!q || !q->ndesc)
+ return;
+
+- /* clear descriptors */
+- for (i = 0; i < q->ndesc; i++)
+- q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++ if (!mt76_queue_is_wed_rro_ind(q)) {
++ int i;
+
+- Q_WRITE(dev, q, cpu_idx, 0);
+- Q_WRITE(dev, q, dma_idx, 0);
++ /* clear descriptors */
++ for (i = 0; i < q->ndesc; i++)
++ q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++ }
++
++ if (reset_idx) {
++ Q_WRITE(q, cpu_idx, 0);
++ Q_WRITE(q, dma_idx, 0);
++ }
+ mt76_dma_sync_idx(dev, q);
+ }
+
++static void
++mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
++{
++ __mt76_dma_queue_reset(dev, q, true);
++}
++
+ static int
+ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ struct mt76_queue_buf *buf, void *data)
+ {
+- struct mt76_desc *desc = &q->desc[q->head];
+ struct mt76_queue_entry *entry = &q->entry[q->head];
+ struct mt76_txwi_cache *txwi = NULL;
++ struct mt76_desc *desc;
+ u32 buf1 = 0, ctrl;
+ int idx = q->head;
+ int rx_token;
+
++ if (mt76_queue_is_wed_rro_ind(q)) {
++ struct mt76_wed_rro_desc *rro_desc;
++
++ rro_desc = (struct mt76_wed_rro_desc *)q->desc;
++ data = &rro_desc[q->head];
++ goto done;
++ }
++
++ desc = &q->desc[q->head];
+ ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+
+ if (mt76_queue_is_wed_rx(q)) {
+@@ -244,6 +267,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
+ WRITE_ONCE(desc->info, 0);
+
++done:
+ entry->dma_addr[0] = buf->addr;
+ entry->dma_len[0] = buf->len;
+ entry->txwi = txwi;
+@@ -343,7 +367,7 @@ static void
+ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+ wmb();
+- Q_WRITE(dev, q, cpu_idx, q->head);
++ Q_WRITE(q, cpu_idx, q->head);
+ }
+
+ static void
+@@ -359,7 +383,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+ if (flush)
+ last = -1;
+ else
+- last = Q_READ(dev, q, dma_idx);
++ last = Q_READ(q, dma_idx);
+
+ while (q->queued > 0 && q->tail != last) {
+ mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
+@@ -371,7 +395,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+ }
+
+ if (!flush && q->tail == last)
+- last = Q_READ(dev, q, dma_idx);
++ last = Q_READ(q, dma_idx);
+ }
+ spin_unlock_bh(&q->cleanup_lock);
+
+@@ -392,10 +416,14 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ {
+ struct mt76_queue_entry *e = &q->entry[idx];
+ struct mt76_desc *desc = &q->desc[idx];
+- void *buf;
++ void *buf = e->buf;
++ u32 ctrl;
+
++ if (mt76_queue_is_wed_rro_ind(q))
++ goto done;
++
++ ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ if (len) {
+- u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ *len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
+ *more = !(ctrl & MT_DMA_CTL_LAST_SEC0);
+ }
+@@ -403,6 +431,12 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ if (info)
+ *info = le32_to_cpu(desc->info);
+
++ if (drop) {
++ *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
++ if (ctrl & MT_DMA_CTL_VER_MASK)
++ *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
++ }
++
+ if (mt76_queue_is_wed_rx(q)) {
+ u32 buf1 = le32_to_cpu(desc->buf1);
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
+@@ -420,23 +454,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ t->ptr = NULL;
+
+ mt76_put_rxwi(dev, t);
+-
+- if (drop) {
+- u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+-
+- *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
+- MT_DMA_CTL_DROP));
+-
++ if (drop)
+ *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
+- }
+ } else {
+- buf = e->buf;
+- e->buf = NULL;
+ dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
+ SKB_WITH_OVERHEAD(q->buf_size),
+ page_pool_get_dma_dir(q->page_pool));
+ }
+
++done:
++ e->buf = NULL;
+ return buf;
+ }
+
+@@ -450,11 +477,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+ if (!q->queued)
+ return NULL;
+
+- if (flush)
+- q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+- else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
++ if (mt76_queue_is_wed_rro_data(q))
+ return NULL;
+
++ if (!mt76_queue_is_wed_rro_ind(q)) {
++ if (flush)
++ q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++ else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
++ return NULL;
++ }
++
+ q->tail = (q->tail + 1) % q->ndesc;
+ q->queued--;
+
+@@ -606,11 +638,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+ spin_lock_bh(&q->lock);
+
+ while (q->queued < q->ndesc - 1) {
++ struct mt76_queue_buf qbuf = {};
+ enum dma_data_direction dir;
+- struct mt76_queue_buf qbuf;
+ dma_addr_t addr;
+ int offset;
+- void *buf;
++ void *buf = NULL;
++
++ if (mt76_queue_is_wed_rro_ind(q))
++ goto done;
+
+ buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
+ if (!buf)
+@@ -621,6 +656,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+ dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
+
+ qbuf.addr = addr + q->buf_offset;
++done:
+ qbuf.len = len - q->buf_offset;
+ qbuf.skip_unmap = false;
+ if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
+@@ -630,7 +666,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+ frames++;
+ }
+
+- if (frames)
++ if (frames || mt76_queue_is_wed_rx(q))
+ mt76_dma_kick_queue(dev, q);
+
+ spin_unlock_bh(&q->lock);
+@@ -641,15 +677,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+- struct mtk_wed_device *wed = &dev->mmio.wed;
+- int ret, type, ring;
+- u8 flags;
++ int ret = 0, type, ring;
++ u16 flags;
+
+ if (!q || !q->ndesc)
+ return -EINVAL;
+
+ flags = q->flags;
+- if (!mtk_wed_device_active(wed))
++ if (!q->wed || !mtk_wed_device_active(q->wed))
+ q->flags &= ~MT_QFLAG_WED;
+
+ if (!(q->flags & MT_QFLAG_WED))
+@@ -660,29 +695,52 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+
+ switch (type) {
+ case MT76_WED_Q_TX:
+- ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs, reset);
++ ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs,
++ reset);
+ if (!ret)
+- q->wed_regs = wed->tx_ring[ring].reg_base;
++ q->wed_regs = q->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, false);
+- q->flags = flags;
+
+- ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
++ ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
+ if (!ret)
+- q->wed_regs = wed->txfree_ring.reg_base;
++ q->wed_regs = q->wed->txfree_ring.reg_base;
+ break;
+ case MT76_WED_Q_RX:
+- ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
++ ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs,
++ reset);
+ if (!ret)
+- q->wed_regs = wed->rx_ring[ring].reg_base;
++ q->wed_regs = q->wed->rx_ring[ring].reg_base;
++ break;
++ case MT76_WED_RRO_Q_DATA:
++ q->flags &= ~MT_QFLAG_WED;
++ __mt76_dma_queue_reset(dev, q, false);
++ mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
++ q->head = q->ndesc - 1;
++ q->queued = q->head;
++ break;
++ case MT76_WED_RRO_Q_MSDU_PG:
++ q->flags &= ~MT_QFLAG_WED;
++ __mt76_dma_queue_reset(dev, q, false);
++ mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
++ q->head = q->ndesc - 1;
++ q->queued = q->head;
++ break;
++ case MT76_WED_RRO_Q_IND:
++ q->flags &= ~MT_QFLAG_WED;
++ mt76_dma_queue_reset(dev, q);
++ mt76_dma_rx_fill(dev, q, false);
++ mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
+ break;
+ default:
+ ret = -EINVAL;
++ break;
+ }
++ q->flags = flags;
+
+ return ret;
+ #else
+@@ -706,11 +764,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ 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);
++ size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc)
++ : sizeof(struct mt76_desc);
++ q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size,
++ &q->desc_dma, GFP_KERNEL);
+ if (!q->desc)
+ return -ENOMEM;
+
++ if (mt76_queue_is_wed_rro_ind(q)) {
++ struct mt76_wed_rro_desc *rro_desc;
++ int i;
++
++ rro_desc = (struct mt76_wed_rro_desc *)q->desc;
++ for (i = 0; i < q->ndesc; i++) {
++ struct mt76_wed_rro_ind *cmd;
++
++ cmd = (struct mt76_wed_rro_ind *)&rro_desc[i];
++ cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1;
++ }
++ }
++
+ size = q->ndesc * sizeof(*q->entry);
+ q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
+ if (!q->entry)
+@@ -724,8 +797,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ if (ret)
+ return ret;
+
+- if (q->flags != MT_WED_Q_TXFREE)
+- mt76_dma_queue_reset(dev, q);
++ if (mtk_wed_device_active(&dev->mmio.wed)) {
++ if ((mtk_wed_get_rx_capa(&dev->mmio.wed) && mt76_queue_is_wed_rro(q)) ||
++ mt76_queue_is_wed_tx_free(q))
++ return 0;
++ }
++
++ mt76_dma_queue_reset(dev, q);
+
+ return 0;
+ }
+@@ -746,7 +824,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+ if (!buf)
+ break;
+
+- mt76_put_page_pool_buf(buf, false);
++ if (!mt76_queue_is_wed_rro(q))
++ mt76_put_page_pool_buf(buf, false);
+ } while (1);
+
+ if (q->rx_head) {
+@@ -761,19 +840,22 @@ static void
+ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+ {
+ struct mt76_queue *q = &dev->q_rx[qid];
+- int i;
+
+ if (!q->ndesc)
+ return;
+
+- for (i = 0; i < q->ndesc; i++)
+- q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++ if (!mt76_queue_is_wed_rro_ind(q)) {
++ int i;
++
++ for (i = 0; i < q->ndesc; i++)
++ q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++ }
+
+ mt76_dma_rx_cleanup(dev, q);
+
+ /* reset WED rx queues */
+ mt76_dma_wed_setup(dev, q, true);
+- if (q->flags != MT_WED_Q_TXFREE) {
++ if (!mt76_queue_is_wed_tx_free(q)) {
+ mt76_dma_sync_idx(dev, q);
+ mt76_dma_rx_fill(dev, q, false);
+ }
+@@ -816,8 +898,8 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ bool more;
+
+ if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
+- q->flags == MT_WED_Q_TXFREE) {
+- dma_idx = Q_READ(dev, q, dma_idx);
++ mt76_queue_is_wed_tx_free(q)) {
++ dma_idx = Q_READ(q, dma_idx);
+ check_ddone = true;
+ }
+
+@@ -827,7 +909,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+
+ if (check_ddone) {
+ if (q->tail == dma_idx)
+- dma_idx = Q_READ(dev, q, dma_idx);
++ dma_idx = Q_READ(q, dma_idx);
+
+ if (q->tail == dma_idx)
+ break;
+@@ -979,16 +1061,23 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ mt76_for_each_q_rx(dev, i) {
+ struct mt76_queue *q = &dev->q_rx[i];
+
++ if (mtk_wed_device_active(&dev->mmio.wed) &&
++ mt76_queue_is_wed_rro(q))
++ continue;
++
+ netif_napi_del(&dev->napi[i]);
+ mt76_dma_rx_cleanup(dev, q);
+
+ page_pool_destroy(q->page_pool);
+ }
+
+- mt76_free_pending_txwi(dev);
+- mt76_free_pending_rxwi(dev);
+-
+ if (mtk_wed_device_active(&dev->mmio.wed))
+ mtk_wed_device_detach(&dev->mmio.wed);
++
++ if (mtk_wed_device_active(&dev->mmio.wed_hif2))
++ mtk_wed_device_detach(&dev->mmio.wed_hif2);
++
++ mt76_free_pending_txwi(dev);
++ mt76_free_pending_rxwi(dev);
+ }
+ EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
+diff --git a/dma.h b/dma.h
+index 1b090d7..22b79d5 100644
+--- a/dma.h
++++ b/dma.h
+@@ -25,6 +25,13 @@
+ #define MT_DMA_PPE_ENTRY GENMASK(30, 16)
+ #define MT_DMA_INFO_PPE_VLD BIT(31)
+
++#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
++#define MT_DMA_CTL_VER_MASK BIT(7)
++
++#define MT_DMA_RRO_EN BIT(13)
++
++#define MT_DMA_WED_IND_CMD_CNT 8
++
+ #define MT_DMA_HDR_LEN 4
+ #define MT_RX_INFO_LEN 4
+ #define MT_FCE_INFO_LEN 4
+@@ -37,6 +44,11 @@ struct mt76_desc {
+ __le32 info;
+ } __packed __aligned(4);
+
++struct mt76_wed_rro_desc {
++ __le32 buf0;
++ __le32 buf1;
++} __packed __aligned(4);
++
+ enum mt76_qsel {
+ MT_QSEL_MGMT,
+ MT_QSEL_HCCA,
+diff --git a/mac80211.c b/mac80211.c
+index 12fcb2b..cd102dd 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -1726,7 +1726,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, void *wed, u32 flags)
+ {
+ struct mt76_queue *hwq;
+ int err;
+@@ -1736,6 +1736,7 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
+ return ERR_PTR(-ENOMEM);
+
+ hwq->flags = flags;
++ hwq->wed = wed;
+
+ err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
+ if (err < 0)
+@@ -1843,3 +1844,19 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
+ return MT_DFS_STATE_ACTIVE;
+ }
+ EXPORT_SYMBOL_GPL(mt76_phy_dfs_state);
++
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++ struct net_device *netdev, enum tc_setup_type type,
++ void *type_data)
++{
++ struct mt76_phy *phy = hw->priv;
++ struct mtk_wed_device *wed = &phy->dev->mmio.wed;
++
++ if (!mtk_wed_device_active(wed))
++ return -EOPNOTSUPP;
++
++ return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
++}
++EXPORT_SYMBOL_GPL(mt76_net_setup_tc);
++#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
+diff --git a/mmio.c b/mmio.c
+index 86e3d2a..c346249 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -4,6 +4,7 @@
+ */
+
+ #include "mt76.h"
++#include "dma.h"
+ #include "trace.h"
+
+ static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset)
+@@ -84,6 +85,102 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
+ }
+ EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
++{
++ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++ int i;
++
++ for (i = 0; i < dev->rx_token_size; i++) {
++ struct mt76_txwi_cache *t;
++
++ t = mt76_rx_token_release(dev, i);
++ if (!t || !t->ptr)
++ continue;
++
++ mt76_put_page_pool_buf(t->ptr, false);
++ t->ptr = NULL;
++
++ mt76_put_rxwi(dev, t);
++ }
++
++ mt76_free_pending_rxwi(dev);
++}
++EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);
++
++u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
++{
++ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++ struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
++ struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
++ int i, len = SKB_WITH_OVERHEAD(q->buf_size);
++ struct mt76_txwi_cache *t = NULL;
++
++ for (i = 0; i < size; i++) {
++ enum dma_data_direction dir;
++ dma_addr_t addr;
++ u32 offset;
++ int token;
++ void *buf;
++
++ t = mt76_get_rxwi(dev);
++ if (!t)
++ goto unmap;
++
++ buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
++ if (!buf)
++ goto unmap;
++
++ addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
++ dir = page_pool_get_dma_dir(q->page_pool);
++ dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
++
++ desc->buf0 = cpu_to_le32(addr);
++ token = mt76_rx_token_consume(dev, buf, t, addr);
++ if (token < 0) {
++ mt76_put_page_pool_buf(buf, false);
++ goto unmap;
++ }
++
++ desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
++ token));
++ desc++;
++ }
++
++ return 0;
++
++unmap:
++ if (t)
++ mt76_put_rxwi(dev, t);
++ mt76_mmio_wed_release_rx_buf(wed);
++
++ return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf);
++
++int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed)
++{
++ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++
++ spin_lock_bh(&dev->token_lock);
++ dev->token_size = wed->wlan.token_start;
++ spin_unlock_bh(&dev->token_lock);
++
++ return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ);
++}
++EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable);
++
++void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed)
++{
++ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++
++ spin_lock_bh(&dev->token_lock);
++ dev->token_size = dev->drv->token_size;
++ spin_unlock_bh(&dev->token_lock);
++}
++EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable);
++#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
++
+ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
+ {
+ static const struct mt76_bus_ops mt76_mmio_ops = {
+diff --git a/mt76.h b/mt76.h
+index a238216..7f93210 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -28,15 +28,22 @@
+ #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_QFLAG_WED_TYPE GENMASK(4, 2)
++#define MT_QFLAG_WED BIT(5)
++#define MT_QFLAG_WED_RRO BIT(6)
++#define MT_QFLAG_WED_RRO_EN BIT(7)
+
+ #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_RRO_Q(_type, _n) (MT_QFLAG_WED_RRO | __MT_WED_Q(_type, _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)
++#define MT_WED_RRO_Q_DATA(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n)
++#define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n)
++#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
+
+ struct mt76_dev;
+ struct mt76_phy;
+@@ -58,6 +65,9 @@ enum mt76_wed_type {
+ MT76_WED_Q_TX,
+ MT76_WED_Q_TXFREE,
+ MT76_WED_Q_RX,
++ MT76_WED_RRO_Q_DATA,
++ MT76_WED_RRO_Q_MSDU_PG,
++ MT76_WED_RRO_Q_IND,
+ };
+
+ struct mt76_bus_ops {
+@@ -106,6 +116,16 @@ enum mt76_rxq_id {
+ MT_RXQ_MAIN_WA,
+ MT_RXQ_BAND2,
+ MT_RXQ_BAND2_WA,
++ MT_RXQ_RRO_BAND0,
++ MT_RXQ_RRO_BAND1,
++ MT_RXQ_RRO_BAND2,
++ MT_RXQ_MSDU_PAGE_BAND0,
++ MT_RXQ_MSDU_PAGE_BAND1,
++ MT_RXQ_MSDU_PAGE_BAND2,
++ MT_RXQ_TXFREE_BAND0,
++ MT_RXQ_TXFREE_BAND1,
++ MT_RXQ_TXFREE_BAND2,
++ MT_RXQ_RRO_IND,
+ __MT_RXQ_MAX
+ };
+
+@@ -183,6 +203,7 @@ struct mt76_queue {
+ spinlock_t lock;
+ spinlock_t cleanup_lock;
+ struct mt76_queue_entry *entry;
++ struct mt76_rro_desc *rro_desc;
+ struct mt76_desc *desc;
+
+ u16 first;
+@@ -196,8 +217,9 @@ struct mt76_queue {
+
+ u8 buf_offset;
+ u8 hw_idx;
+- u8 flags;
++ u16 flags;
+
++ struct mtk_wed_device *wed;
+ u32 wed_regs;
+
+ dma_addr_t desc_dma;
+@@ -352,6 +374,17 @@ struct mt76_txq {
+ bool aggr;
+ };
+
++struct mt76_wed_rro_ind {
++ u32 se_id : 12;
++ u32 rsv : 4;
++ u32 start_sn : 12;
++ u32 ind_reason : 4;
++ u32 ind_cnt : 13;
++ u32 win_sz : 3;
++ u32 rsv2 : 13;
++ u32 magic_cnt : 3;
++};
++
+ struct mt76_txwi_cache {
+ struct list_head list;
+ dma_addr_t dma_addr;
+@@ -602,6 +635,7 @@ struct mt76_mmio {
+ u32 irqmask;
+
+ struct mtk_wed_device wed;
++ struct mtk_wed_device wed_hif2;
+ struct completion wed_reset;
+ struct completion wed_reset_complete;
+ };
+@@ -1046,6 +1080,12 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
+ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
+ void mt76_pci_disable_aspm(struct pci_dev *pdev);
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++ struct net_device *netdev, enum tc_setup_type type,
++ void *type_data);
++#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
++
+ static inline u16 mt76_chip(struct mt76_dev *dev)
+ {
+ return dev->rev >> 16;
+@@ -1056,6 +1096,13 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
+ return dev->rev & 0xffff;
+ }
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
++void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed);
++int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed);
++void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed);
++#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
++
+ #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76))
+ #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76))
+
+@@ -1105,15 +1152,16 @@ 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, void *wed, u32 flags);
+ u16 mt76_calculate_default_rate(struct mt76_phy *phy,
+ struct ieee80211_vif *vif, 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, void *wed,
++ u32 flags)
+ {
+ 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, wed, flags);
+ if (IS_ERR(q))
+ return PTR_ERR(q);
+
+@@ -1127,7 +1175,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, NULL, 0);
+ if (IS_ERR(q))
+ return PTR_ERR(q);
+
+@@ -1541,10 +1589,38 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ struct mt76_power_limits *dest,
+ s8 target_power);
+
+-static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
++static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q)
+ {
+ return (q->flags & MT_QFLAG_WED) &&
+- FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
++ FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
++}
++
++static inline bool mt76_queue_is_wed_rro(struct mt76_queue *q)
++{
++ return q->flags & MT_QFLAG_WED_RRO;
++}
++
++static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
++{
++ return mt76_queue_is_wed_rro(q) &&
++ FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND;
++}
++
++static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q)
++{
++ return mt76_queue_is_wed_rro(q) &&
++ (FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA ||
++ FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_MSDU_PG);
++}
++
++static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
++{
++ if (!(q->flags & MT_QFLAG_WED))
++ return false;
++
++ return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX ||
++ mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q);
++
+ }
+
+ struct mt76_txwi_cache *
+@@ -1584,10 +1660,14 @@ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
+ static inline int
+ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+ {
+- int token;
++ int token, start = 0;
++
++ if (mtk_wed_device_active(&dev->mmio.wed))
++ start = dev->mmio.wed.wlan.nbuf;
+
+ spin_lock_bh(&dev->token_lock);
+- token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
++ token = idr_alloc(&dev->token, *ptxwi, start, start + dev->token_size,
++ GFP_ATOMIC);
+ spin_unlock_bh(&dev->token_lock);
+
+ return token;
+diff --git a/mt7603/dma.c b/mt7603/dma.c
+index 03ba11a..7a2f5d3 100644
+--- a/mt7603/dma.c
++++ b/mt7603/dma.c
+@@ -173,13 +173,14 @@ 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,
++ NULL, 0);
+ 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, NULL, 0);
+ if (ret)
+ return ret;
+
+@@ -189,12 +190,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, NULL, 0);
+ 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, NULL, 0);
+ if (ret)
+ return ret;
+
+diff --git a/mt7615/dma.c b/mt7615/dma.c
+index 0ce01cc..e7135b2 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, NULL, 0);
+ 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, NULL, 0);
+ 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_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE,
+- MT_TX_RING_BASE, 0);
++ MT_TX_RING_BASE, NULL, 0);
+ if (ret)
+ return ret;
+
+diff --git a/mt76_connac.h b/mt76_connac.h
+index 1f29d8c..e5ebde1 100644
+--- a/mt76_connac.h
++++ b/mt76_connac.h
+@@ -391,7 +391,8 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
+
+ void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss);
+ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
+- int ring_base, u32 flags);
++ int ring_base, void *wed, u32 flags);
++
+ void mt76_connac_write_hw_txp(struct mt76_dev *dev,
+ struct mt76_tx_info *tx_info,
+ void *txp_ptr, u32 id);
+diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
+index 93402d2..c791464 100644
+--- a/mt76_connac_mac.c
++++ b/mt76_connac_mac.c
+@@ -256,11 +256,12 @@ void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
+ EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap);
+
+ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
+- int ring_base, u32 flags)
++ int ring_base, void *wed, u32 flags)
+ {
+ int i, err;
+
+- err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags);
++ err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base,
++ wed, flags);
+ if (err < 0)
+ return err;
+
+diff --git a/mt76x02_mmio.c b/mt76x02_mmio.c
+index 9b5e3fb..e5ad635 100644
+--- a/mt76x02_mmio.c
++++ b/mt76x02_mmio.c
+@@ -199,13 +199,14 @@ 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, NULL, 0);
+ 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,
++ NULL, 0);
+ if (ret)
+ return ret;
+
+diff --git a/mt7915/dma.c b/mt7915/dma.c
+index 59a44d7..1bceeb5 100644
+--- a/mt7915/dma.c
++++ b/mt7915/dma.c
+@@ -9,18 +9,20 @@ static int
+ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
+ {
+ struct mt7915_dev *dev = phy->dev;
++ struct mtk_wed_device *wed = NULL;
+
+- if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+ if (is_mt798x(&dev->mt76))
+ ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
+ else
+ ring_base = MT_WED_TX_RING_BASE;
+
+ idx -= MT_TXQ_ID(0);
++ wed = &dev->mt76.mmio.wed;
+ }
+
+ return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base,
+- MT_WED_Q_TX(idx));
++ wed, MT_WED_Q_TX(idx));
+ }
+
+ static int mt7915_poll_tx(struct napi_struct *napi, int budget)
+@@ -492,7 +494,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ if (mtk_wed_device_active(&mdev->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;
++ mdev->q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
++ mdev->q_rx[MT_RXQ_MCU_WA].wed = &mdev->mmio.wed;
+ } else {
+ wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA);
+ wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA);
+@@ -507,9 +510,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ if (!dev->phy.mt76->band_idx) {
+ if (mtk_wed_device_active(&mdev->mmio.wed) &&
+ mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
+- dev->mt76.q_rx[MT_RXQ_MAIN].flags =
++ mdev->q_rx[MT_RXQ_MAIN].flags =
+ MT_WED_Q_RX(MT7915_RXQ_BAND0);
+ dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
++ mdev->q_rx[MT_RXQ_MAIN].wed = &mdev->mmio.wed;
+ }
+
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
+@@ -528,6 +532,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+
+ if (mtk_wed_device_active(&mdev->mmio.wed)) {
+ mdev->q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
++ mdev->q_rx[MT_RXQ_MAIN_WA].wed = &mdev->mmio.wed;
+ if (is_mt7916(mdev)) {
+ wa_rx_base = MT_WED_RX_RING_BASE;
+ wa_rx_idx = MT7915_RXQ_MCU_WA;
+@@ -544,9 +549,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ if (dev->dbdc_support || dev->phy.mt76->band_idx) {
+ if (mtk_wed_device_active(&mdev->mmio.wed) &&
+ mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
+- dev->mt76.q_rx[MT_RXQ_BAND1].flags =
++ mdev->q_rx[MT_RXQ_BAND1].flags =
+ MT_WED_Q_RX(MT7915_RXQ_BAND1);
+ dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
++ mdev->q_rx[MT_RXQ_BAND1].wed = &mdev->mmio.wed;
+ }
+
+ /* rx data queue for band1 */
+@@ -643,7 +649,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
+
+ mt76_for_each_q_rx(&dev->mt76, i) {
+- if (dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE)
++ if (mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
+ continue;
+
+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
+diff --git a/mt7915/main.c b/mt7915/main.c
+index a3fd54c..ba34c8e 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -1653,20 +1653,6 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
+
+ return 0;
+ }
+-
+-static int
+-mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+- struct net_device *netdev, enum tc_setup_type type,
+- void *type_data)
+-{
+- struct mt7915_dev *dev = mt7915_hw_dev(hw);
+- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+-
+- if (!mtk_wed_device_active(wed))
+- return -EOPNOTSUPP;
+-
+- return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
+-}
+ #endif
+
+ const struct ieee80211_ops mt7915_ops = {
+@@ -1721,6 +1707,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_setup_tc = mt7915_net_setup_tc,
++ .net_setup_tc = mt76_net_setup_tc,
+ #endif
+ };
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index fc7ace6..85cb3fe 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -542,105 +542,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ }
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+-static int mt7915_mmio_wed_offload_enable(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;
+- spin_unlock_bh(&dev->mt76.token_lock);
+-
+- return !wait_event_timeout(dev->mt76.tx_wait,
+- !dev->mt76.wed_token_count, HZ);
+-}
+-
+-static void mt7915_mmio_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);
+-}
+-
+-static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+-{
+- struct mt7915_dev *dev;
+- int i;
+-
+- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+- for (i = 0; i < dev->mt76.rx_token_size; i++) {
+- struct mt76_txwi_cache *t;
+-
+- t = mt76_rx_token_release(&dev->mt76, i);
+- if (!t || !t->ptr)
+- continue;
+-
+- mt76_put_page_pool_buf(t->ptr, false);
+- t->ptr = NULL;
+-
+- mt76_put_rxwi(&dev->mt76, t);
+- }
+-
+- mt76_free_pending_rxwi(&dev->mt76);
+-}
+-
+-static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+-{
+- struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
+- struct mt76_txwi_cache *t = NULL;
+- struct mt7915_dev *dev;
+- struct mt76_queue *q;
+- int i, len;
+-
+- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+- q = &dev->mt76.q_rx[MT_RXQ_MAIN];
+- len = SKB_WITH_OVERHEAD(q->buf_size);
+-
+- for (i = 0; i < size; i++) {
+- enum dma_data_direction dir;
+- dma_addr_t addr;
+- u32 offset;
+- int token;
+- void *buf;
+-
+- t = mt76_get_rxwi(&dev->mt76);
+- if (!t)
+- goto unmap;
+-
+- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
+- if (!buf)
+- goto unmap;
+-
+- addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
+- dir = page_pool_get_dma_dir(q->page_pool);
+- dma_sync_single_for_device(dev->mt76.dma_dev, addr, len, dir);
+-
+- desc->buf0 = cpu_to_le32(addr);
+- token = mt76_rx_token_consume(&dev->mt76, buf, t, addr);
+- if (token < 0) {
+- mt76_put_page_pool_buf(buf, false);
+- goto unmap;
+- }
+-
+- desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
+- token));
+- desc++;
+- }
+-
+- return 0;
+-
+-unmap:
+- if (t)
+- mt76_put_rxwi(&dev->mt76, t);
+- mt7915_mmio_wed_release_rx_buf(wed);
+- return -ENOMEM;
+-}
+-
+ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed,
+ struct mtk_wed_wo_rx_stats *stats)
+ {
+@@ -778,10 +679,10 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
+ }
+
+ wed->wlan.init_buf = mt7915_wed_init_buf;
+- wed->wlan.offload_enable = mt7915_mmio_wed_offload_enable;
+- wed->wlan.offload_disable = mt7915_mmio_wed_offload_disable;
+- wed->wlan.init_rx_buf = mt7915_mmio_wed_init_rx_buf;
+- wed->wlan.release_rx_buf = mt7915_mmio_wed_release_rx_buf;
++ wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
++ wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
++ wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
++ wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
+ wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats;
+ wed->wlan.reset = mt7915_mmio_wed_reset;
+ wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete;
+diff --git a/mt7921/pci.c b/mt7921/pci.c
+index 9647e4b..9ea7e0c 100644
+--- a/mt7921/pci.c
++++ b/mt7921/pci.c
+@@ -171,7 +171,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev)
+ /* init tx queue */
+ ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
+ MT7921_TX_RING_SIZE,
+- MT_TX_RING_BASE, 0);
++ MT_TX_RING_BASE, NULL, 0);
+ if (ret)
+ return ret;
+
+diff --git a/mt7925/pci.c b/mt7925/pci.c
+index 08ef75e..734f31e 100644
+--- a/mt7925/pci.c
++++ b/mt7925/pci.c
+@@ -218,7 +218,7 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
+ /* init tx queue */
+ ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0,
+ MT7925_TX_RING_SIZE,
+- MT_TX_RING_BASE, 0);
++ MT_TX_RING_BASE, NULL, 0);
+ if (ret)
+ return ret;
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 586e247..2221d22 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -7,6 +7,26 @@
+ #include "../dma.h"
+ #include "mac.h"
+
++int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
++ int ring_base, struct mtk_wed_device *wed)
++{
++ struct mt7996_dev *dev = phy->dev;
++ u32 flags = 0;
++
++ if (mtk_wed_device_active(wed)) {
++ ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
++ idx -= MT_TXQ_ID(0);
++
++ if (phy->mt76->band_idx == MT_BAND2)
++ flags = MT_WED_Q_TX(0);
++ else
++ flags = MT_WED_Q_TX(idx);
++ }
++
++ return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc,
++ ring_base, wed, flags);
++}
++
+ static int mt7996_poll_tx(struct napi_struct *napi, int budget)
+ {
+ struct mt7996_dev *dev;
+@@ -45,6 +65,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+ RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
+ RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
+
++ if (dev->has_rro) {
++ /* band0 */
++ RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
++ MT7996_RXQ_RRO_BAND0);
++ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
++ MT7996_RXQ_MSDU_PG_BAND0);
++ RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
++ MT7996_RXQ_TXFREE0);
++ /* band1 */
++ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
++ MT7996_RXQ_MSDU_PG_BAND1);
++ /* band2 */
++ RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
++ MT7996_RXQ_RRO_BAND2);
++ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
++ MT7996_RXQ_MSDU_PG_BAND2);
++ RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
++ MT7996_RXQ_TXFREE2);
++
++ RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
++ MT7996_RXQ_RRO_IND);
++ }
++
+ /* data tx queue */
+ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
+ TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
+@@ -73,6 +116,24 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10));
+
++ if (dev->has_rro) {
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
++ PREFETCH(0x3a0, 0x10));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
++ PREFETCH(0x4a0, 0x10));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
++ PREFETCH(0x5a0, 0x4));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
++ PREFETCH(0x5e0, 0x4));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
++ PREFETCH(0x620, 0x4));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
++ PREFETCH(0x660, 0x4));
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
++ PREFETCH(0x6a0, 0x4));
++ }
++#undef PREFETCH
++
+ mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
+ }
+
+@@ -128,8 +189,9 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
+ }
+ }
+
+-void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
++void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ {
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ u32 hif1_ofs = 0;
+ u32 irq_mask;
+
+@@ -138,11 +200,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
+
+ /* enable WFDMA Tx/Rx */
+ if (!reset) {
+- mt76_set(dev, MT_WFDMA0_GLO_CFG,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
++ mt76_set(dev, MT_WFDMA0_GLO_CFG,
++ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO);
++ else
++ mt76_set(dev, MT_WFDMA0_GLO_CFG,
++ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++ MT_WFDMA0_GLO_CFG_RX_DMA_EN |
++ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+
+ if (dev->hif2)
+ mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+@@ -153,11 +220,7 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
+ }
+
+ /* enable interrupts for TX/RX rings */
+- irq_mask = MT_INT_MCU_CMD;
+- if (reset)
+- goto done;
+-
+- irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
++ irq_mask = MT_INT_MCU_CMD | MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
+
+ if (!dev->mphy.band_idx)
+ irq_mask |= MT_INT_BAND0_RX_DONE;
+@@ -168,7 +231,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
+ if (dev->tbtc_support)
+ irq_mask |= MT_INT_BAND2_RX_DONE;
+
+-done:
++ if (mtk_wed_device_active(wed) && wed_reset) {
++ u32 wed_irq_mask = irq_mask;
++
++ wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
++ mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
++ mtk_wed_device_start(wed, wed_irq_mask);
++ }
++
++ irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
++
+ mt7996_irq_enable(dev, irq_mask);
+ mt7996_irq_disable(dev, 0);
+ }
+@@ -241,17 +313,90 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ /* fix hardware limitation, pcie1's rx ring3 is not available
+ * so, redirect pcie0 rx ring3 interrupt to pcie1
+ */
+- mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
+- MT_WFDMA0_RX_INT_SEL_RING3);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++ dev->has_rro)
++ mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
++ MT_WFDMA0_RX_INT_SEL_RING6);
++ else
++ mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
++ MT_WFDMA0_RX_INT_SEL_RING3);
++ }
++
++ mt7996_dma_start(dev, reset, true);
++}
++
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++int mt7996_dma_rro_init(struct mt7996_dev *dev)
++{
++ struct mt76_dev *mdev = &dev->mt76;
++ u32 irq_mask;
++ int ret;
++
++ /* ind cmd */
++ mdev->q_rx[MT_RXQ_RRO_IND].flags = MT_WED_RRO_Q_IND;
++ mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed;
++ ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_IND],
++ MT_RXQ_ID(MT_RXQ_RRO_IND),
++ MT7996_RX_RING_SIZE,
++ 0, MT_RXQ_RRO_IND_RING_BASE);
++ if (ret)
++ return ret;
+
+- /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
++ /* rx msdu page queue for band0 */
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags =
++ MT_WED_RRO_Q_MSDU_PG(0) | MT_QFLAG_WED_RRO_EN;
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
++ ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
++ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
++ MT7996_RX_RING_SIZE,
++ MT7996_RX_MSDU_PAGE_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
++ if (ret)
++ return ret;
++
++ if (dev->dbdc_support) {
++ /* rx msdu page queue for band1 */
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags =
++ MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN;
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
++ ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
++ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
++ MT7996_RX_RING_SIZE,
++ MT7996_RX_MSDU_PAGE_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
++ if (ret)
++ return ret;
++ }
++
++ if (dev->tbtc_support) {
++ /* rx msdu page queue for band2 */
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags =
++ MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN;
++ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
++ ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
++ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
++ MT7996_RX_RING_SIZE,
++ MT7996_RX_MSDU_PAGE_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
++ if (ret)
++ return ret;
+ }
+
+- mt7996_dma_start(dev, reset);
++ irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE |
++ MT_INT_TX_DONE_BAND2;
++ mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
++ mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);
++ mt7996_irq_enable(dev, irq_mask);
++
++ return 0;
+ }
++#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
+
+ int mt7996_dma_init(struct mt7996_dev *dev)
+ {
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++ struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
++ u32 rx_base;
+ u32 hif1_ofs = 0;
+ int ret;
+
+@@ -265,10 +410,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ mt7996_dma_disable(dev, true);
+
+ /* init tx queue */
+- ret = mt76_connac_init_tx_queues(dev->phy.mt76,
+- MT_TXQ_ID(dev->mphy.band_idx),
+- MT7996_TX_RING_SIZE,
+- MT_TXQ_RING_BASE(0), 0);
++ ret = mt7996_init_tx_queues(&dev->phy,
++ MT_TXQ_ID(dev->mphy.band_idx),
++ MT7996_TX_RING_SIZE,
++ MT_TXQ_RING_BASE(0),
++ wed);
+ if (ret)
+ return ret;
+
+@@ -315,6 +461,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ return ret;
+
+ /* rx data queue for band0 and band1 */
++ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
++ dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0);
++ dev->mt76.q_rx[MT_RXQ_MAIN].wed = wed;
++ }
++
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
+ MT_RXQ_ID(MT_RXQ_MAIN),
+ MT7996_RX_RING_SIZE,
+@@ -324,6 +475,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ return ret;
+
+ /* tx free notify event from WA for band0 */
++ if (mtk_wed_device_active(wed) && !dev->has_rro) {
++ dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
++ dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
++ }
++
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
+ MT_RXQ_ID(MT_RXQ_MAIN_WA),
+ MT7996_RX_MCU_RING_SIZE,
+@@ -334,17 +490,23 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+
+ if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
+ /* rx data queue for band2 */
++ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ MT_RXQ_ID(MT_RXQ_BAND2),
+ MT7996_RX_RING_SIZE,
+ MT_RX_BUF_SIZE,
+- MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs);
++ rx_base);
+ if (ret)
+ return ret;
+
+ /* tx free notify event from WA for band2
+ * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
+ */
++ if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) {
++ dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE;
++ dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2;
++ }
++
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2_WA],
+ MT_RXQ_ID(MT_RXQ_BAND2_WA),
+ MT7996_RX_MCU_RING_SIZE,
+@@ -354,6 +516,60 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ return ret;
+ }
+
++ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
++ dev->has_rro) {
++ /* rx rro data queue for band0 */
++ dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags =
++ MT_WED_RRO_Q_DATA(0) | MT_QFLAG_WED_RRO_EN;
++ dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed;
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
++ MT_RXQ_ID(MT_RXQ_RRO_BAND0),
++ MT7996_RX_RING_SIZE,
++ MT7996_RX_BUF_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0));
++ if (ret)
++ return ret;
++
++ /* tx free notify event from WA for band0 */
++ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
++ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
++
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
++ MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
++ MT7996_RX_MCU_RING_SIZE,
++ MT7996_RX_BUF_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
++ if (ret)
++ return ret;
++
++ if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
++ /* rx rro data queue for band2 */
++ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
++ MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
++ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
++ MT_RXQ_ID(MT_RXQ_RRO_BAND2),
++ MT7996_RX_RING_SIZE,
++ MT7996_RX_BUF_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
++ if (ret)
++ return ret;
++
++ /* tx free notify event from MAC for band2 */
++ if (mtk_wed_device_active(wed_hif2)) {
++ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE;
++ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].wed = wed_hif2;
++ }
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2],
++ MT_RXQ_ID(MT_RXQ_TXFREE_BAND2),
++ MT7996_RX_MCU_RING_SIZE,
++ MT7996_RX_BUF_SIZE,
++ MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs);
++ if (ret)
++ return ret;
++ }
++ }
++
+ ret = mt76_init_queues(dev, mt76_dma_rx_poll);
+ if (ret < 0)
+ return ret;
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 12c2513..d335b58 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -155,7 +155,7 @@ mt7996_regd_notifier(struct wiphy *wiphy,
+ }
+
+ static void
+-mt7996_init_wiphy(struct ieee80211_hw *hw)
++mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
+ {
+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ struct mt76_dev *mdev = &phy->dev->mt76;
+@@ -167,6 +167,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ hw->max_rx_aggregation_subframes = max_subframes;
+ hw->max_tx_aggregation_subframes = max_subframes;
+ hw->netdev_features = NETIF_F_RXCSUM;
++ if (mtk_wed_device_active(wed))
++ hw->netdev_features |= NETIF_F_HW_TC;
+
+ hw->radiotap_timestamp.units_pos =
+ IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
+@@ -312,8 +314,13 @@ void mt7996_mac_init(struct mt7996_dev *dev)
+
+ /* rro module init */
+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
+- mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
+- mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
++ if (dev->has_rro) {
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
++ } else {
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
++ }
+
+ mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+ MCU_WA_PARAM_HW_PATH_HIF_VER,
+@@ -350,6 +357,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ struct mt76_phy *mphy;
+ u32 mac_ofs, hif1_ofs = 0;
+ int ret;
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+
+ if (band != MT_BAND1 && band != MT_BAND2)
+ return 0;
+@@ -361,8 +369,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ if (phy)
+ return 0;
+
+- if (band == MT_BAND2 && dev->hif2)
++ if (band == MT_BAND2 && dev->hif2) {
+ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++ wed = &dev->mt76.mmio.wed_hif2;
++ }
+
+ mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band);
+ if (!mphy)
+@@ -395,11 +405,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ mt76_eeprom_override(mphy);
+
+ /* init wiphy according to mphy and phy */
+- mt7996_init_wiphy(mphy->hw);
+- ret = mt76_connac_init_tx_queues(phy->mt76,
+- MT_TXQ_ID(band),
+- MT7996_TX_RING_SIZE,
+- MT_TXQ_RING_BASE(band) + hif1_ofs, 0);
++ mt7996_init_wiphy(mphy->hw, wed);
++ ret = mt7996_init_tx_queues(mphy->priv,
++ MT_TXQ_ID(band),
++ MT7996_TX_RING_SIZE,
++ MT_TXQ_RING_BASE(band) + hif1_ofs,
++ wed);
+ if (ret)
+ goto error;
+
+@@ -412,6 +423,13 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ if (ret)
+ goto error;
+
++ if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
++ u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
++
++ mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
++ mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask);
++ }
++
+ return 0;
+
+ error:
+@@ -456,6 +474,120 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
+ msleep(20);
+ }
+
++static int mt7996_wed_rro_init(struct mt7996_dev *dev)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++ u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
++ struct mt7996_wed_rro_addr *addr;
++ void *ptr;
++ int i;
++
++ if (!dev->has_rro)
++ return 0;
++
++ if (!mtk_wed_device_active(wed))
++ return 0;
++
++ for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
++ ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_BA_BITMAP_CR_SIZE,
++ &dev->wed_rro.ba_bitmap[i].phy_addr,
++ GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
++
++ dev->wed_rro.ba_bitmap[i].ptr = ptr;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
++ int j;
++
++ ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr),
++ &dev->wed_rro.addr_elem[i].phy_addr,
++ GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
++
++ dev->wed_rro.addr_elem[i].ptr = ptr;
++ memset(dev->wed_rro.addr_elem[i].ptr, 0,
++ MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr));
++
++ addr = dev->wed_rro.addr_elem[i].ptr;
++ for (j = 0; j < MT7996_RRO_WINDOW_MAX_SIZE; j++) {
++ addr->signature = 0xff;
++ addr++;
++ }
++
++ wed->wlan.ind_cmd.addr_elem_phys[i] =
++ dev->wed_rro.addr_elem[i].phy_addr;
++ }
++
++ ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
++ &dev->wed_rro.session.phy_addr,
++ GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
++
++ dev->wed_rro.session.ptr = ptr;
++ addr = dev->wed_rro.session.ptr;
++ for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
++ addr->signature = 0xff;
++ addr++;
++ }
++
++ /* rro hw init */
++ /* TODO: remove line after WM has set */
++ mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
++
++ /* setup BA bitmap cache address */
++ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
++ dev->wed_rro.ba_bitmap[0].phy_addr);
++ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
++ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
++ dev->wed_rro.ba_bitmap[1].phy_addr);
++ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
++
++ /* setup Address element address */
++ for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
++ mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4);
++ reg += 4;
++ }
++
++ /* setup Address element address - separate address segment mode */
++ mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
++ MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
++
++ wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
++ wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
++ wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
++ wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
++ wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
++
++ mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
++ mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
++ MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
++
++ /* particular session configure */
++ /* use max session idx + 1 as particular session id */
++ mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
++ mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
++ MT_RRO_PARTICULAR_CONFG_EN |
++ FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION));
++
++ /* interrupt enable */
++ mt76_wr(dev, MT_RRO_HOST_INT_ENA,
++ MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
++
++ /* rro ind cmd queue init */
++ return mt7996_dma_rro_init(dev);
++#else
++ return 0;
++#endif
++}
++
+ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ {
+ int ret, idx;
+@@ -477,6 +609,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
++ ret = mt7996_wed_rro_init(dev);
++ if (ret)
++ return ret;
++
+ ret = mt7996_eeprom_init(dev);
+ if (ret < 0)
+ return ret;
+@@ -884,7 +1020,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
+- mt7996_init_wiphy(hw);
++ mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
+
+ ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+ ARRAY_SIZE(mt76_rates));
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 1a1e218..4be5410 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -449,8 +449,36 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
+ return 0;
+ }
+
++static void
++mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
++ struct mt7996_sta *msta, struct sk_buff *skb,
++ u32 info)
++{
++ struct ieee80211_vif *vif;
++ struct wireless_dev *wdev;
++
++ if (!msta || !msta->vif)
++ return;
++
++ if (!mt76_queue_is_wed_rx(q))
++ return;
++
++ if (!(info & MT_DMA_INFO_PPE_VLD))
++ return;
++
++ vif = container_of((void *)msta->vif, struct ieee80211_vif,
++ drv_priv);
++ wdev = ieee80211_vif_to_wdev(vif);
++ skb->dev = wdev->netdev;
++
++ mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
++ FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
++ FIELD_GET(MT_DMA_PPE_ENTRY, info));
++}
++
+ static int
+-mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
++mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
++ struct sk_buff *skb, u32 *info)
+ {
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ struct mt76_phy *mphy = &dev->mt76.phy;
+@@ -475,7 +503,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ u16 seq_ctrl = 0;
+ __le16 fc = 0;
+ int idx;
++ u8 hw_aggr = false;
++ struct mt7996_sta *msta = NULL;
+
++ hw_aggr = status->aggr;
+ memset(status, 0, sizeof(*status));
+
+ band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
+@@ -502,8 +533,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
+
+ if (status->wcid) {
+- struct mt7996_sta *msta;
+-
+ msta = container_of(status->wcid, struct mt7996_sta, wcid);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ if (list_empty(&msta->wcid.poll_list))
+@@ -708,12 +737,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ }
+ } else {
+ status->flag |= RX_FLAG_8023;
++ mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
++ *info);
+ }
+
+ if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
+ mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
+
+- if (!status->wcid || !ieee80211_is_data_qos(fc))
++ if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
+ return 0;
+
+ status->aggr = unicast &&
+@@ -1010,6 +1041,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ return 0;
+ }
+
++u32 mt7996_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 = BIT(31) |
++ 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
+ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+ {
+@@ -1388,6 +1442,12 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+
+ switch (type) {
+ case PKT_TYPE_TXRX_NOTIFY:
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2) &&
++ q == MT_RXQ_TXFREE_BAND2) {
++ dev_kfree_skb(skb);
++ break;
++ }
++
+ mt7996_mac_tx_free(dev, skb->data, skb->len);
+ napi_consume_skb(skb, 1);
+ break;
+@@ -1404,7 +1464,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ dev_kfree_skb(skb);
+ break;
+ case PKT_TYPE_NORMAL:
+- if (!mt7996_mac_fill_rx(dev, skb)) {
++ if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
+ mt76_rx(&dev->mt76, q, skb);
+ return;
+ }
+@@ -1862,7 +1922,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
+
+ /* enable DMA Tx/Tx and interrupt */
+- mt7996_dma_start(dev, false);
++ mt7996_dma_start(dev, false, false);
+
+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+ clear_bit(MT76_RESET, &dev->mphy.state);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index a2ab668..ae4f0ce 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1368,6 +1368,44 @@ out:
+ return ret;
+ }
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static int
++mt7996_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 mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++ struct mt7996_dev *dev = mt7996_hw_dev(hw);
++ struct mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++
++ if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
++ wed = &dev->mt76.mmio.wed_hif2;
++
++ if (!mtk_wed_device_active(wed))
++ return -ENODEV;
++
++ if (msta->wcid.idx > MT7996_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.queue = 0;
++ path->mtk_wdma.wcid = msta->wcid.idx;
++
++ path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
++ ctx->dev = NULL;
++
++ return 0;
++}
++
++#endif
++
+ const struct ieee80211_ops mt7996_ops = {
+ .tx = mt7996_tx,
+ .start = mt7996_start,
+@@ -1412,4 +1450,8 @@ const struct ieee80211_ops mt7996_ops = {
+ .sta_add_debugfs = mt7996_sta_add_debugfs,
+ #endif
+ .set_radar_background = mt7996_set_radar_background,
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ .net_fill_forward_path = mt7996_net_fill_forward_path,
++ .net_setup_tc = mt76_net_setup_tc,
++#endif
+ };
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 12bf4e5..3ff70c6 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -912,7 +912,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
+ }
+
+ static int
+-mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
++mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif,
+ struct ieee80211_ampdu_params *params,
+ bool enable, bool tx)
+ {
+@@ -921,7 +921,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ struct sk_buff *skb;
+ struct tlv *tlv;
+
+- skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid,
++ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mvif, wcid,
+ MT7996_STA_UPDATE_MAX_SIZE);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+@@ -935,8 +935,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ ba->ba_en = enable << params->tid;
+ ba->amsdu = params->amsdu;
+ ba->tid = params->tid;
++ ba->ba_rdd_rro = !tx && enable && dev->has_rro;
+
+- return mt76_mcu_skb_send_msg(dev, skb,
++ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+ }
+
+@@ -951,8 +952,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
+ if (enable && !params->amsdu)
+ msta->wcid.amsdu = false;
+
+- return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+- enable, true);
++ return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, true);
+ }
+
+ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+@@ -962,8 +962,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+ struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
+ struct mt7996_vif *mvif = msta->vif;
+
+- return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+- enable, false);
++ return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, false);
+ }
+
+ static void
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 3a591a7..c7b6d4b 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -10,6 +10,10 @@
+ #include "mt7996.h"
+ #include "mac.h"
+ #include "../trace.h"
++#include "../dma.h"
++
++static bool wed_enable;
++module_param(wed_enable, bool, 0644);
+
+ static const struct __base mt7996_reg_base[] = {
+ [WF_AGG_BASE] = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
+@@ -191,6 +195,143 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
+ }
+
++int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
++ bool hif2, int *irq)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++ struct pci_dev *pci_dev = pdev_ptr;
++ u32 hif1_ofs = 0;
++ int ret;
++
++ if (!wed_enable)
++ return 0;
++
++ dev->has_rro = true;
++
++ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++
++ if (hif2)
++ wed = &dev->mt76.mmio.wed_hif2;
++
++ wed->wlan.pci_dev = pci_dev;
++ wed->wlan.bus_type = MTK_WED_BUS_PCIE;
++
++ wed->wlan.base = devm_ioremap(dev->mt76.dev,
++ pci_resource_start(pci_dev, 0),
++ pci_resource_len(pci_dev, 0));
++ wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
++
++ if (hif2) {
++ wed->wlan.wpdma_int = wed->wlan.phy_base +
++ MT_INT_PCIE1_SOURCE_CSR_EXT;
++ wed->wlan.wpdma_mask = wed->wlan.phy_base +
++ MT_INT_PCIE1_MASK_CSR;
++ wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
++ MT_TXQ_RING_BASE(0) +
++ MT7996_TXQ_BAND2 * MT_RING_SIZE;
++ if (dev->has_rro) {
++ wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
++ MT_RXQ_RING_BASE(0) +
++ MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
++ wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
++ } else {
++ wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
++ MT_RXQ_RING_BASE(0) +
++ MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
++ wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
++ }
++
++ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
++ wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
++ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
++ MT7996_RXQ_BAND0 * MT_RING_SIZE;
++
++ wed->wlan.id = 0x7991;
++ wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
++ } else {
++ wed->wlan.hw_rro = dev->has_rro; /* default on */
++ wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
++ wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
++ wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
++ MT7996_TXQ_BAND0 * MT_RING_SIZE;
++
++ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
++
++ wed->wlan.wpdma_rx = wed->wlan.phy_base +
++ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
++ MT7996_RXQ_BAND0 * MT_RING_SIZE;
++
++ wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
++ MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
++ MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
++ wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
++ MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
++ MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
++ wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
++ MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
++ MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
++
++ wed->wlan.rx_nbuf = 65536;
++ wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576;
++ wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
++
++ wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
++ wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
++
++ wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
++ wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
++
++ wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
++ wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
++ wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
++
++ wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
++ wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
++ if (dev->has_rro) {
++ wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
++ MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
++ wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
++ } else {
++ wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
++ wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
++ MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
++ }
++ dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
++ }
++
++ wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
++ wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf;
++
++ wed->wlan.amsdu_max_subframes = 8;
++ wed->wlan.amsdu_max_len = 1536;
++
++ wed->wlan.init_buf = mt7996_wed_init_buf;
++ wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
++ wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
++ wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
++ wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
++
++ if (mtk_wed_device_attach(wed))
++ 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;
++
++ ret = dma_set_coherent_mask(wed->dev, DMA_BIT_MASK(32));
++ if (ret)
++ return ret;
++
++ return 1;
++#else
++ return 0;
++#endif
++}
++
+ static int mt7996_mmio_init(struct mt76_dev *mdev,
+ void __iomem *mem_base,
+ u32 device_id)
+@@ -241,8 +382,17 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
+ mdev->mmio.irqmask |= set;
+
+ if (write_reg) {
+- mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
+- mt76_wr(dev, MT_INT1_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);
++ if (mtk_wed_device_active(&mdev->mmio.wed_hif2)) {
++ mtk_wed_device_irq_set_mask(&mdev->mmio.wed_hif2,
++ mdev->mmio.irqmask);
++ }
++ } else {
++ mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
++ mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
++ }
+ }
+
+ spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
+@@ -260,22 +410,36 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
+ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ {
+ struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++ struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
+ u32 i, intr, mask, intr1;
+
+- 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);
+-
+- if (dev->hif2) {
+- intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
+- intr1 &= dev->mt76.mmio.irqmask;
+- mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
++ if (dev->hif2 && mtk_wed_device_active(wed_hif2)) {
++ mtk_wed_device_irq_set_mask(wed_hif2, 0);
++ intr1 = mtk_wed_device_irq_get(wed_hif2,
++ dev->mt76.mmio.irqmask);
++ if (intr1 & MT_INT_RX_TXFREE_EXT)
++ napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
++ }
+
+- intr |= intr1;
++ 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);
++ intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
++ } else {
++ 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);
++ if (dev->hif2) {
++ intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
++ intr1 &= dev->mt76.mmio.irqmask;
++ mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
++ intr |= intr1;
++ }
+ }
+
+ trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
+@@ -308,9 +472,17 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
+ {
+ struct mt7996_dev *dev = dev_instance;
+
+- mt76_wr(dev, MT_INT_MASK_CSR, 0);
+- if (dev->hif2)
+- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++ mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
++ else
++ mt76_wr(dev, MT_INT_MASK_CSR, 0);
++
++ if (dev->hif2) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
++ mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_hif2, 0);
++ else
++ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
++ }
+
+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
+ return IRQ_NONE;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 7354e5c..c541eaa 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -37,6 +37,7 @@
+ #define MT7996_EEPROM_SIZE 7680
+ #define MT7996_EEPROM_BLOCK_SIZE 16
+ #define MT7996_TOKEN_SIZE 16384
++#define MT7996_HW_TOKEN_SIZE 8192
+
+ #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
+ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
+@@ -49,6 +50,22 @@
+ #define MT7996_BASIC_RATES_TBL 11
+ #define MT7996_BEACON_RATES_TBL 25
+
++#define MT7996_RRO_MAX_SESSION 1024
++#define MT7996_RRO_WINDOW_MAX_LEN 1024
++#define MT7996_RRO_ADDR_ELEM_LEN 128
++#define MT7996_RRO_BA_BITMAP_LEN 2
++#define MT7996_RRO_BA_BITMAP_CR_SIZE ((MT7996_RRO_MAX_SESSION * 128) / \
++ MT7996_RRO_BA_BITMAP_LEN)
++#define MT7996_RRO_BA_BITMAP_SESSION_SIZE (MT7996_RRO_MAX_SESSION / \
++ MT7996_RRO_ADDR_ELEM_LEN)
++#define MT7996_RRO_WINDOW_MAX_SIZE (MT7996_RRO_WINDOW_MAX_LEN * \
++ MT7996_RRO_BA_BITMAP_SESSION_SIZE)
++
++#define MT7996_RX_BUF_SIZE (1800 + \
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
++#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -78,6 +95,16 @@ enum mt7996_rxq_id {
+ MT7996_RXQ_BAND0 = 4,
+ MT7996_RXQ_BAND1 = 4,/* unused */
+ MT7996_RXQ_BAND2 = 5,
++ MT7996_RXQ_RRO_BAND0 = 8,
++ MT7996_RXQ_RRO_BAND1 = 8,/* unused */
++ MT7996_RXQ_RRO_BAND2 = 6,
++ MT7996_RXQ_MSDU_PG_BAND0 = 10,
++ MT7996_RXQ_MSDU_PG_BAND1 = 11,
++ MT7996_RXQ_MSDU_PG_BAND2 = 12,
++ MT7996_RXQ_TXFREE0 = 9,
++ MT7996_RXQ_TXFREE1 = 9,
++ MT7996_RXQ_TXFREE2 = 7,
++ MT7996_RXQ_RRO_IND = 0,
+ };
+
+ struct mt7996_twt_flow {
+@@ -147,6 +174,15 @@ struct mt7996_hif {
+ int irq;
+ };
+
++struct mt7996_wed_rro_addr {
++ u32 head_low;
++ u32 head_high : 4;
++ u32 count: 11;
++ u32 oor: 1;
++ u32 rsv : 8;
++ u32 signature : 8;
++};
++
+ struct mt7996_phy {
+ struct mt76_phy *mt76;
+ struct mt7996_dev *dev;
+@@ -226,6 +262,22 @@ struct mt7996_dev {
+ bool tbtc_support:1;
+ bool flash_mode:1;
+ bool has_eht:1;
++ bool has_rro:1;
++
++ struct {
++ struct {
++ void *ptr;
++ dma_addr_t phy_addr;
++ } ba_bitmap[MT7996_RRO_BA_BITMAP_LEN];
++ struct {
++ void *ptr;
++ dma_addr_t phy_addr;
++ } addr_elem[MT7996_RRO_ADDR_ELEM_LEN];
++ struct {
++ void *ptr;
++ dma_addr_t phy_addr;
++ } session;
++ } wed_rro;
+
+ bool ibf;
+ u8 fw_debug_wm;
+@@ -335,7 +387,9 @@ int mt7996_dma_init(struct mt7996_dev *dev);
+ void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+ void mt7996_dma_cleanup(struct mt7996_dev *dev);
+-void mt7996_dma_start(struct mt7996_dev *dev, bool reset);
++void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset);
++int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
++ int n_desc, int ring_base, struct mtk_wed_device *wed);
+ void mt7996_init_txpower(struct mt7996_dev *dev,
+ struct ieee80211_supported_band *sband);
+ int mt7996_txbf_init(struct mt7996_dev *dev);
+@@ -495,5 +549,16 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct dentry *dir);
+ #endif
++int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
++ bool hif2, int *irq);
++u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
++
++#ifdef CONFIG_MTK_DEBUG
++int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
++#endif
++
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++int mt7996_dma_rro_init(struct mt7996_dev *dev);
++#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
+
+ #endif
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index c530105..92869ca 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -125,15 +125,26 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ mt7996_wfsys_reset(dev);
+ hif2 = mt7996_pci_init_hif2(pdev);
+
+- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++ ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
+ if (ret < 0)
+- goto free_device;
++ goto free_wed_or_irq_vector;
+
+- irq = pdev->irq;
+- ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
++ if (!ret) {
++ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++ if (ret < 0)
++ goto free_device;
++ }
++ ret = devm_request_irq(mdev->dev, pdev->irq, mt7996_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret)
+- goto free_irq_vector;
++ goto free_wed_or_irq_vector;
++
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++ ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
++ IRQF_SHARED, KBUILD_MODNAME "-wed", dev);
++ if (ret)
++ goto free_irq;
++ }
+
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ /* master switch of PCIe tnterrupt enable */
+@@ -143,16 +154,30 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
+ dev->hif2 = hif2;
+
+- ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
++ ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &irq);
+ if (ret < 0)
+- goto free_hif2;
++ goto free_irq;
++
++ if (!ret) {
++ ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
++ if (ret < 0)
++ goto free_hif2;
+
+- dev->hif2->irq = hif2_dev->irq;
+- ret = devm_request_irq(mdev->dev, dev->hif2->irq,
+- mt7996_irq_handler, IRQF_SHARED,
+- KBUILD_MODNAME "-hif", dev);
++ dev->hif2->irq = hif2_dev->irq;
++ }
++
++ ret = devm_request_irq(mdev->dev, hif2_dev->irq, mt7996_irq_handler,
++ IRQF_SHARED, KBUILD_MODNAME "-hif", dev);
+ if (ret)
+- goto free_hif2_irq_vector;
++ goto free_hif2;
++
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) {
++ ret = devm_request_irq(mdev->dev, irq,
++ mt7996_irq_handler, IRQF_SHARED,
++ KBUILD_MODNAME "-wed-hif", dev);
++ if (ret)
++ goto free_hif2_irq_vector;
++ }
+
+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ /* master switch of PCIe tnterrupt enable */
+@@ -168,15 +193,28 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ free_hif2_irq:
+ if (dev->hif2)
+ devm_free_irq(mdev->dev, dev->hif2->irq, dev);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
++ devm_free_irq(mdev->dev, dev->mt76.mmio.wed_hif2.irq, dev);
+ free_hif2_irq_vector:
+- if (dev->hif2)
+- pci_free_irq_vectors(hif2_dev);
++ if (dev->hif2) {
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
++ mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);
++ else
++ pci_free_irq_vectors(hif2_dev);
++ }
+ free_hif2:
+ if (dev->hif2)
+ put_device(dev->hif2->dev);
+- devm_free_irq(mdev->dev, irq, dev);
+-free_irq_vector:
+- pci_free_irq_vectors(pdev);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++ devm_free_irq(mdev->dev, dev->mt76.mmio.wed.irq, dev);
++free_irq:
++ devm_free_irq(mdev->dev, pdev->irq, dev);
++free_wed_or_irq_vector:
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++ mtk_wed_device_detach(&dev->mt76.mmio.wed);
++ else
++ pci_free_irq_vectors(pdev);
++
+ free_device:
+ mt76_free_device(&dev->mt76);
+
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 5702290..854390d 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -39,6 +39,38 @@ enum base_rev {
+
+ #define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
+
++/* RRO TOP */
++#define MT_RRO_TOP_BASE 0xA000
++#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
++
++#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8)
++#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
++#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
++#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
++#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
++#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
++
++#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38)
++#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C)
++#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40)
++#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31)
++
++#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C)
++#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60)
++#define MT_RRO_PARTICULAR_CONFG_EN BIT(31)
++#define MT_RRO_PARTICULAR_SID GENMASK(30, 16)
++
++#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70)
++#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74)
++#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204)
++#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0)
++
++#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
++
++#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
++#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
++#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
++
+ #define MT_MCU_INT_EVENT 0x2108
+ #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
+ #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
+@@ -323,6 +355,7 @@ enum base_rev {
+
+ #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
+ #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
++#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)
+
+ #define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
+
+@@ -367,6 +400,9 @@ enum base_rev {
+ #define MT_WFDMA0_PCIE1_BASE 0xd8000
+ #define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
+
++#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118)
++#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c)
++
+ #define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)
+ #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0)
+ #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
+@@ -387,6 +423,7 @@ enum base_rev {
+ #define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300)
+ #define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300)
+ #define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
++#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
+
+ #define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
+ MT_MCUQ_ID(q) * 0x4)
+@@ -412,6 +449,15 @@ enum base_rev {
+ #define MT_INT_RX_TXFREE_MAIN BIT(17)
+ #define MT_INT_RX_TXFREE_TRI BIT(15)
+ #define MT_INT_MCU_CMD BIT(29)
++#define MT_INT_RX_TXFREE_EXT BIT(26)
++
++#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
++#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
++#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
++#define MT_INT_RX_DONE_RRO_IND BIT(11)
++#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
++#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
++#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
+
+ #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
+ #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
+@@ -420,20 +466,31 @@ enum base_rev {
+ MT_INT_RX(MT_RXQ_MCU_WA))
+
+ #define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
+- MT_INT_RX(MT_RXQ_MAIN_WA))
++ MT_INT_RX(MT_RXQ_MAIN_WA) | \
++ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
+
+ #define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
+ MT_INT_RX(MT_RXQ_BAND1_WA) | \
+- MT_INT_RX(MT_RXQ_MAIN_WA))
++ MT_INT_RX(MT_RXQ_MAIN_WA) | \
++ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
+
+ #define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \
+ MT_INT_RX(MT_RXQ_BAND2_WA) | \
+- MT_INT_RX(MT_RXQ_MAIN_WA))
++ MT_INT_RX(MT_RXQ_MAIN_WA) | \
++ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
++
++#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
++ MT_INT_RX(MT_RXQ_RRO_BAND1) | \
++ MT_INT_RX(MT_RXQ_RRO_BAND2) | \
++ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
++ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
++ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
+
+ #define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
+ MT_INT_BAND0_RX_DONE | \
+ MT_INT_BAND1_RX_DONE | \
+- MT_INT_BAND2_RX_DONE)
++ MT_INT_BAND2_RX_DONE | \
++ MT_INT_RRO_RX_DONE)
+
+ #define MT_INT_TX_DONE_FWDL BIT(26)
+ #define MT_INT_TX_DONE_MCU_WM BIT(27)
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch
deleted file mode 100644
index 4342d73..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch
+++ /dev/null
@@ -1,198 +0,0 @@
-From 20c8d7bfeb91be51129e7e98213db441a62d6d95 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Wed, 31 May 2023 18:31:41 +0800
-Subject: [PATCH 03/11] wifi: mt76: connac: add support for dsp firmware
- download
-
-Add FW_START_WORKING_PDA_DSP for the indication of starting DSP
-firmware download, which is for phy-related control.
-The firmware is transparent to the driver, but it's necessary for the
-firmware download process.
-
-Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: I35666504cfe7bf213c8f8f0c0223b3089372f2ab
----
-v2:
- - merge two commits
- - move main load ram code to a regular function
-v3:
- - remove all macros to directly call __mt7996_load_ram()
- - add back missing code which records fw_version to wiphy
----
- mt76_connac_mcu.h | 1 +
- mt7996/mcu.c | 67 +++++++++++++++++++++++------------------------
- mt7996/mt7996.h | 7 +++++
- mt7996/pci.c | 1 +
- 4 files changed, 42 insertions(+), 34 deletions(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 91d98eff..d2a3d56b 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -22,6 +22,7 @@
-
- #define FW_START_OVERRIDE BIT(0)
- #define FW_START_WORKING_PDA_CR4 BIT(2)
-+#define FW_START_WORKING_PDA_DSP BIT(3)
-
- #define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0)
- #define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 88e2f9d0..545cc987 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2155,7 +2155,7 @@ out:
- static int
- mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
- const struct mt7996_fw_trailer *hdr,
-- const u8 *data, bool is_wa)
-+ const u8 *data, enum mt7996_ram_type type)
- {
- int i, offset = 0;
- u32 override = 0, option = 0;
-@@ -2167,8 +2167,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
-
- region = (const struct mt7996_fw_region *)((const u8 *)hdr -
- (hdr->n_region - i) * sizeof(*region));
-+ /* DSP and WA use same mode */
- mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
-- region->feature_set, is_wa);
-+ region->feature_set,
-+ type != MT7996_RAM_TYPE_WM);
- len = le32_to_cpu(region->len);
- addr = le32_to_cpu(region->addr);
-
-@@ -2195,19 +2197,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
- if (override)
- option |= FW_START_OVERRIDE;
-
-- if (is_wa)
-+ if (type == MT7996_RAM_TYPE_WA)
- option |= FW_START_WORKING_PDA_CR4;
-+ else if (type == MT7996_RAM_TYPE_DSP)
-+ option |= FW_START_WORKING_PDA_DSP;
-
- return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
- }
-
--static int mt7996_load_ram(struct mt7996_dev *dev)
-+static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
-+ const char *fw_file, enum mt7996_ram_type ram_type)
- {
- const struct mt7996_fw_trailer *hdr;
- const struct firmware *fw;
- int ret;
-
-- ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
-+ ret = request_firmware(&fw, fw_file, dev->mt76.dev);
- if (ret)
- return ret;
-
-@@ -2217,37 +2222,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
- goto out;
- }
-
-- hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
--
-- dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
-- hdr->fw_ver, hdr->build_date);
-+ hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
-+ dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n",
-+ fw_type, hdr->fw_ver, hdr->build_date);
-
-- ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
-+ ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type);
- if (ret) {
-- dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
-- goto out;
-- }
--
-- release_firmware(fw);
--
-- ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
-- if (ret)
-- return ret;
--
-- if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
-- dev_err(dev->mt76.dev, "Invalid firmware\n");
-- ret = -EINVAL;
-- goto out;
-- }
--
-- hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
--
-- dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
-- hdr->fw_ver, hdr->build_date);
--
-- ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
-- if (ret) {
-- dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
-+ dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type);
- goto out;
- }
-
-@@ -2261,6 +2242,24 @@ out:
- return ret;
- }
-
-+static int mt7996_load_ram(struct mt7996_dev *dev)
-+{
-+ int ret;
-+
-+ ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
-+ MT7996_RAM_TYPE_WM);
-+ if (ret)
-+ return ret;
-+
-+ ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP,
-+ MT7996_RAM_TYPE_DSP);
-+ if (ret)
-+ return ret;
-+
-+ return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA,
-+ MT7996_RAM_TYPE_WA);
-+}
-+
- static int
- mt7996_firmware_state(struct mt7996_dev *dev, bool wa)
- {
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 4d7dcb95..7dfdc738 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -29,6 +29,7 @@
-
- #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
- #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
-+#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
- #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
-
- #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
-@@ -52,6 +53,12 @@ struct mt7996_sta;
- struct mt7996_dfs_pulse;
- struct mt7996_dfs_pattern;
-
-+enum mt7996_ram_type {
-+ MT7996_RAM_TYPE_WM,
-+ MT7996_RAM_TYPE_WA,
-+ MT7996_RAM_TYPE_DSP,
-+};
-+
- enum mt7996_txq_id {
- MT7996_TXQ_FWDL = 16,
- MT7996_TXQ_MCU_WM,
-diff --git a/mt7996/pci.c b/mt7996/pci.c
-index 64aee3fb..c5301050 100644
---- a/mt7996/pci.c
-+++ b/mt7996/pci.c
-@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
- MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
- MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
- MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
-+MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
- MODULE_FIRMWARE(MT7996_ROM_PATCH);
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
similarity index 87%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
index 798eb69..c657c5b 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
@@ -1,7 +1,7 @@
-From 7390e5db3745febd580026e723b2ca806e308008 Mon Sep 17 00:00:00 2001
+From 0d8aff6fa4ee351350dda83f8cc7ca2b557322ac Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Fri, 14 Apr 2023 16:51:59 +0800
-Subject: [PATCH 30/39] wifi: mt76: mt7996: add support for auxiliary path
+Subject: [PATCH 03/98] wifi: mt76: mt7996: add support for auxiliary path
Add support to correctly configure the setting of variants that have
additional TX or RX path.
@@ -17,10 +17,10 @@
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index f5e9546..9840c77 100644
+index 544b6c6..9db7e53 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
-@@ -171,36 +171,49 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
+@@ -148,36 +148,49 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
{
@@ -75,10 +75,10 @@
mphy->antenna_mask = BIT(nss) - 1;
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 0f8f0cd..9ea3667 100644
+index 0c74977..412d6e2 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
-@@ -34,6 +34,9 @@ enum mt7996_eeprom_field {
+@@ -33,6 +33,9 @@ enum mt7996_eeprom_field {
#define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
@@ -89,10 +89,10 @@
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 7b8f883..a2c1e43 100644
+index 3ff70c6..328bea9 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -3198,7 +3198,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
+@@ -3178,7 +3178,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
.center_ch = ieee80211_frequency_to_channel(freq1),
.bw = mt76_connac_chan_bw(chandef),
.tx_path_num = hweight16(phy->mt76->chainmask),
@@ -102,19 +102,19 @@
.channel_band = ch_band[chandef->chan->band],
};
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index f7d6580..8e5b3c3 100644
+index c541eaa..ef84173 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -248,6 +248,8 @@ struct mt7996_phy {
- struct mib_stats mib;
- struct mt76_channel_state state_ts;
+@@ -206,6 +206,8 @@ struct mt7996_phy {
-+ bool has_aux_rx;
+ struct mt76_mib_stats mib;
+ struct mt76_channel_state state_ts;
+
- #ifdef CONFIG_NL80211_TESTMODE
- struct {
- u32 *reg_backup;
-@@ -551,6 +553,18 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
++ bool has_aux_rx;
+ };
+
+ struct mt7996_dev {
+@@ -491,6 +493,18 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
size_t len);
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
similarity index 71%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
index ba0e378..bb8761d 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
@@ -1,7 +1,7 @@
-From fd7730026ccef8b0d5a52ac07ddb21af48def17d Mon Sep 17 00:00:00 2001
+From f6b0399c4e70fb8fa521d53e59bc933e491271c3 Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Thu, 20 Apr 2023 16:34:47 +0800
-Subject: [PATCH 32/39] wifi: mt76: mt7996: add eht mode tx stats
+Subject: [PATCH 04/98] wifi: mt76: mt7996: add eht mode tx stats
Add eht mode bf fbk stats and bw320 through debugfs tx_stats command
@@ -11,19 +11,19 @@
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 0422018..ca4d615 100644
+index 4d40ec7..9bd9535 100644
--- a/mt7996/debugfs.c
+++ b/mt7996/debugfs.c
-@@ -481,7 +481,7 @@ static void
- mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
+@@ -476,7 +476,7 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
{
+ struct mt76_mib_stats *mib = &phy->mib;
static const char * const bw[] = {
- "BW20", "BW40", "BW80", "BW160"
+ "BW20", "BW40", "BW80", "BW160", "BW320"
};
- struct mib_stats *mib = &phy->mib;
-@@ -495,8 +495,9 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
+ /* Tx Beamformer monitor */
+@@ -489,8 +489,9 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
/* Tx Beamformer Rx feedback monitor */
seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch
deleted file mode 100644
index a4e17a9..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 3c7a5592ea211f5ddb2f6bbd6ba8720c74faf459 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Thu, 2 Mar 2023 15:44:52 +0800
-Subject: [PATCH 04/11] wifi: mt76: mt7996: fix bss wlan_idx when sending
- bss_info command
-
-The bmc_tx_wlan_idx should be the wlan_idx of the current bss rather
-than peer AP's wlan_idx, otherwise there will appear some frame
-decryption problems on station mode.
-
-Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
-Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/mcu.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 545cc987..6706d38c 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -712,6 +712,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- struct cfg80211_chan_def *chandef = &phy->chandef;
- struct mt76_connac_bss_basic_tlv *bss;
- u32 type = CONNECTION_INFRA_AP;
-+ u16 sta_wlan_idx = wlan_idx;
- struct tlv *tlv;
- int idx;
-
-@@ -731,7 +732,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- struct mt76_wcid *wcid;
-
- wcid = (struct mt76_wcid *)sta->drv_priv;
-- wlan_idx = wcid->idx;
-+ sta_wlan_idx = wcid->idx;
- }
- rcu_read_unlock();
- }
-@@ -751,7 +752,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
- bss->dtim_period = vif->bss_conf.dtim_period;
- bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
-- bss->sta_idx = cpu_to_le16(wlan_idx);
-+ bss->sta_idx = cpu_to_le16(sta_wlan_idx);
- bss->conn_type = cpu_to_le32(type);
- bss->omac_idx = mvif->omac_idx;
- bss->band_idx = mvif->band_idx;
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch
similarity index 86%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch
index bcc5d51..9d85c7c 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch
@@ -1,7 +1,7 @@
-From 1fa1645ef7621981c7e87d27b9a7816f3485d3db Mon Sep 17 00:00:00 2001
+From c4d8ad5eb5f4d9929e923fa2c0683a2e24d8ca0c Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Thu, 2 Feb 2023 21:20:31 +0800
-Subject: [PATCH 17/39] wifi: mt76: mt7996: add thermal protection support
+Subject: [PATCH 05/98] wifi: mt76: mt7996: add thermal protection support
This commit includes the following changes:
1. implement MTK thermal protection driver API
@@ -10,27 +10,27 @@
Change-Id: I8fecc28f5b17ee50ae4644d1dd17d188dd694731
---
mt76_connac_mcu.h | 1 +
- mt7996/init.c | 103 ++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/init.c | 103 +++++++++++++++++++++++++++++++++++++++++++++
mt7996/main.c | 8 ++++
- mt7996/mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.h | 44 +++++++++++++++++++
mt7996/mt7996.h | 15 +++++++
- 6 files changed, 277 insertions(+)
+ 6 files changed, 276 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 6249de5..30c9a5d 100644
+index 6064973..99077f1 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1010,6 +1010,7 @@ enum {
- MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
- MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
+@@ -1021,6 +1021,7 @@ enum {
MCU_UNI_EVENT_RDD_REPORT = 0x11,
+ MCU_UNI_EVENT_ROC = 0x27,
+ MCU_UNI_EVENT_TX_DONE = 0x2d,
+ MCU_UNI_EVENT_THERMAL = 0x35,
+ MCU_UNI_EVENT_NIC_CAPAB = 0x43,
};
- #define MCU_UNI_CMD_EVENT BIT(1)
diff --git a/mt7996/init.c b/mt7996/init.c
-index 8247153..c072b09 100644
+index d335b58..610d80e 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -42,6 +42,98 @@ static const struct ieee80211_iface_combination if_comb[] = {
@@ -132,7 +132,7 @@
static void mt7996_led_set_config(struct led_classdev *led_cdev,
u8 delay_on, u8 delay_off)
{
-@@ -391,6 +483,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+@@ -419,6 +511,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
if (ret)
goto error;
@@ -143,7 +143,7 @@
ret = mt7996_init_debugfs(phy);
if (ret)
goto error;
-@@ -411,6 +507,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
+@@ -446,6 +542,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
if (!phy)
return;
@@ -152,7 +152,7 @@
mphy = phy->dev->mt76.phys[band];
mt76_unregister_phy(mphy);
ieee80211_free_hw(mphy->hw);
-@@ -882,6 +980,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1027,6 +1125,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
@@ -163,7 +163,7 @@
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
-@@ -905,6 +1007,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
+@@ -1050,6 +1152,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
{
mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
@@ -172,7 +172,7 @@
mt76_unregister_device(&dev->mt76);
mt7996_mcu_exit(dev);
diff --git a/mt7996/main.c b/mt7996/main.c
-index 02a33b8..9c80839 100644
+index ae4f0ce..280120b 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -51,6 +51,14 @@ int mt7996_run(struct ieee80211_hw *hw)
@@ -183,7 +183,7 @@
+ if (ret)
+ goto out;
+
-+ ret = mt7996_mcu_set_thermal_protect(phy);
++ ret = mt7996_mcu_set_thermal_protect(phy, true);
+ if (ret)
+ goto out;
+
@@ -191,10 +191,10 @@
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index c50dcce..c308d86 100644
+index 328bea9..5310f9b 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -447,6 +447,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -449,6 +449,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
@@ -229,7 +229,7 @@
static void
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
-@@ -491,6 +519,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -493,6 +521,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_RDD_REPORT:
mt7996_mcu_rx_radar_detected(dev, skb);
break;
@@ -239,7 +239,7 @@
default:
break;
}
-@@ -3217,6 +3248,81 @@ out:
+@@ -3450,6 +3481,80 @@ out:
return 0;
}
@@ -277,7 +277,7 @@
+ return 0;
+}
+
-+int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy)
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable)
+{
+#define SUSTAIN_PERIOD 10
+ struct {
@@ -302,13 +302,12 @@
+
+ ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
+ &req, sizeof(req) - sizeof(req.enable), false);
-+ if (ret)
++ if (ret || !enable)
+ return ret;
+
+ /* set high-temperature trigger threshold */
+ req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_ENABLE);
-+ /* add a safety margin ~10 */
-+ req.enable.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10);
++ req.enable.restore_temp = cpu_to_le32(phy->throttle_temp[0]);
+ req.enable.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
+ req.enable.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
+
@@ -322,7 +321,7 @@
{
struct {
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 078f828..f235175 100644
+index e4b3122..f1528df 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
@@ -377,7 +376,7 @@
enum mt7996_chan_mib_offs {
UNI_MIB_OBSS_AIRTIME = 26,
UNI_MIB_NON_WIFI_TIME = 27,
-@@ -659,6 +697,12 @@ enum{
+@@ -656,6 +694,12 @@ enum{
UNI_CMD_SR_SET_SIGA = 0xd0,
};
@@ -391,10 +390,10 @@
UNI_CMD_ACCESS_REG_BASIC = 0x0,
UNI_CMD_ACCESS_RF_REG_BASIC,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 651f53a..071031b 100644
+index ef84173..e1972e9 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -49,6 +49,13 @@
+@@ -50,6 +50,13 @@
#define MT7996_BASIC_RATES_TBL 11
#define MT7996_BEACON_RATES_TBL 25
@@ -405,10 +404,10 @@
+#define MT7996_CRIT_TEMP 110
+#define MT7996_MAX_TEMP 120
+
- struct mt7996_vif;
- struct mt7996_sta;
- struct mt7996_dfs_pulse;
-@@ -217,6 +224,11 @@ struct mt7996_phy {
+ #define MT7996_RRO_MAX_SESSION 1024
+ #define MT7996_RRO_WINDOW_MAX_LEN 1024
+ #define MT7996_RRO_ADDR_ELEM_LEN 128
+@@ -191,6 +198,11 @@ struct mt7996_phy {
struct ieee80211_vif *monitor_vif;
@@ -420,13 +419,13 @@
u32 rxfilter;
u64 omac_mask;
-@@ -466,6 +478,9 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+@@ -445,6 +457,9 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
+int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
+int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
-+int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy);
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val);
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
deleted file mode 100644
index d4968dd..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 56d84272851f6c77cf68186bc8906de0558d2e5b Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 17 Mar 2023 11:08:04 +0800
-Subject: [PATCH 05/11] wifi: mt76: mt7996: init he and eht cap for AP_VLAN
-
-Init he and eht capabilities for AP_VLAN type. Without this patch, the
-BA response from AP_VLAN will not include the ADDBA extension tag.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/init.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index f1b48cdd..004575a0 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -808,6 +808,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
- switch (i) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_AP:
-+ case NL80211_IFTYPE_AP_VLAN:
- #ifdef CONFIG_MAC80211_MESH
- case NL80211_IFTYPE_MESH_POINT:
- #endif
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
similarity index 83%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
index effc63b..a4338f3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
@@ -1,15 +1,15 @@
-From db282c765c1d9cd2a5eec6a095069fd4bcf627b4 Mon Sep 17 00:00:00 2001
+From 3bf4da3eba0f082ec3be1c0ee603cbae3e9d9fbb Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Thu, 2 Feb 2023 20:53:42 +0800
-Subject: [PATCH 18/39] wifi: mt76: mt7996: add thermal sensor device support
+Subject: [PATCH 06/98] wifi: mt76: mt7996: add thermal sensor device support
---
- mt7996/init.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/init.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.c | 41 ++++++++++++++++++++++++
- 2 files changed, 128 insertions(+)
+ 2 files changed, 129 insertions(+)
diff --git a/mt7996/init.c b/mt7996/init.c
-index c072b09..0319e7f 100644
+index 610d80e..de4a5f7 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -4,6 +4,8 @@
@@ -21,7 +21,7 @@
#include <linux/thermal.h>
#include "mt7996.h"
#include "mac.h"
-@@ -42,6 +44,81 @@ static const struct ieee80211_iface_combination if_comb[] = {
+@@ -42,6 +44,82 @@ static const struct ieee80211_iface_combination if_comb[] = {
}
};
@@ -66,12 +66,13 @@
+ mutex_lock(&phy->dev->mt76.mutex);
+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130);
+
++ /* add a safety margin ~10 */
+ if ((i - 1 == MT7996_CRIT_TEMP_IDX &&
-+ val > phy->throttle_temp[MT7996_MAX_TEMP_IDX]) ||
++ val > phy->throttle_temp[MT7996_MAX_TEMP_IDX] - 10) ||
+ (i - 1 == MT7996_MAX_TEMP_IDX &&
-+ val < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
++ val - 10 < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
+ dev_err(phy->dev->mt76.dev,
-+ "temp1_max shall be greater than temp1_crit.");
++ "temp1_max shall be 10 degrees higher than temp1_crit.");
+ mutex_unlock(&phy->dev->mt76.mutex);
+ return -EINVAL;
+ }
@@ -79,7 +80,7 @@
+ phy->throttle_temp[i - 1] = val;
+ mutex_unlock(&phy->dev->mt76.mutex);
+
-+ ret = mt7996_mcu_set_thermal_protect(phy);
++ ret = mt7996_mcu_set_thermal_protect(phy, true);
+ if (ret)
+ return ret;
+
@@ -103,7 +104,7 @@
static int
mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
unsigned long *state)
-@@ -113,6 +190,7 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+@@ -113,6 +191,7 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
{
struct wiphy *wiphy = phy->mt76->hw->wiphy;
struct thermal_cooling_device *cdev;
@@ -111,7 +112,7 @@
const char *name;
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
-@@ -131,6 +209,15 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+@@ -131,6 +210,15 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
@@ -128,10 +129,10 @@
}
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index c308d86..349c20e 100644
+index 5310f9b..8320c8c 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -3248,6 +3248,47 @@ out:
+@@ -3481,6 +3481,47 @@ out:
return 0;
}
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch
deleted file mode 100644
index 348a04a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 1e7bbf8c04d60eb6cd234990f94da73bccd73118 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 27 Mar 2023 14:30:25 +0800
-Subject: [PATCH 06/11] wifi: mt76: mt7996: enable VHT extended NSS BW feature
-
-Set SUPPORTS_VHT_EXT_NSS_BW to let the max BW capability correctly be
-parsed by different devices.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/init.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 004575a0..8247153d 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -217,6 +217,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
- phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
- IEEE80211_HT_MPDU_DENSITY_1;
-+
-+ ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
- }
-
- mt76_set_stream_caps(phy->mt76, true);
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch
deleted file mode 100644
index 8021427..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-From edca876e34fc2696e8f855c2d05036fa79a05f8f Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Thu, 1 Jun 2023 12:01:10 +0800
-Subject: [PATCH 07/11] wifi: mt76: connac: add support to set ifs time by mcu
- command
-
-There's a race between driver and fw on some tx/rx control registers
-when setting ifs, which will cause accidental hw queue pause problems.
-Avoid this by setting ifs time with bss_info mcu command.
-
-Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: Ib6477462a35df84a89f113a4db0e6aef5154c6a8
----
-v2:
- - merge two commits
- - change bool a_band to use is_2ghz
----
- mt76_connac_mcu.h | 1 +
- mt7996/mac.c | 27 ++-------------------------
- mt7996/main.c | 5 ++---
- mt7996/mcu.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.h | 17 +++++++++++++++++
- mt7996/mt7996.h | 3 ++-
- 6 files changed, 70 insertions(+), 29 deletions(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index d2a3d56b..b91262ee 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -1288,6 +1288,7 @@ enum {
- UNI_BSS_INFO_UAPSD = 19,
- UNI_BSS_INFO_PS = 21,
- UNI_BSS_INFO_BCNFT = 22,
-+ UNI_BSS_INFO_IFS_TIME = 23,
- UNI_BSS_INFO_OFFLOAD = 25,
- UNI_BSS_INFO_MLD = 26,
- };
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 23cbfdde..2da61d2e 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1612,20 +1612,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy)
- mt7996_mcu_get_chan_mib_info(phy, true);
- }
-
--void mt7996_mac_set_timing(struct mt7996_phy *phy)
-+void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
- {
- s16 coverage_class = phy->coverage_class;
- struct mt7996_dev *dev = phy->dev;
- struct mt7996_phy *phy2 = mt7996_phy2(dev);
- struct mt7996_phy *phy3 = mt7996_phy3(dev);
-- u32 val, reg_offset;
-+ u32 reg_offset;
- u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
- FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
- u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
- FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
- u8 band_idx = phy->mt76->band_idx;
- int offset;
-- bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
-
- if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
- return;
-@@ -1638,34 +1637,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy)
- coverage_class = max_t(s16, coverage_class,
- phy3->coverage_class);
-
-- mt76_set(dev, MT_ARB_SCR(band_idx),
-- MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
-- udelay(1);
--
- offset = 3 * coverage_class;
- reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
- FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
-
- mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset);
- mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset);
-- mt76_wr(dev, MT_TMAC_ICR0(band_idx),
-- FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
-- FIELD_PREP(MT_IFS_RIFS, 2) |
-- FIELD_PREP(MT_IFS_SIFS, 10) |
-- FIELD_PREP(MT_IFS_SLOT, phy->slottime));
--
-- if (!a_band)
-- mt76_wr(dev, MT_TMAC_ICR1(band_idx),
-- FIELD_PREP(MT_IFS_EIFS_CCK, 314));
--
-- if (phy->slottime < 20 || a_band)
-- val = MT7996_CFEND_RATE_DEFAULT;
-- else
-- val = MT7996_CFEND_RATE_11B;
--
-- mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val);
-- mt76_clear(dev, MT_ARB_SCR(band_idx),
-- MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
- }
-
- void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band)
-diff --git a/mt7996/main.c b/mt7996/main.c
-index e7c97d2f..786c3fbc 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -287,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy)
- if (ret)
- goto out;
-
-- mt7996_mac_set_timing(phy);
- ret = mt7996_dfs_init_radar_detector(phy);
- mt7996_mac_cca_stats_reset(phy);
-
-@@ -564,7 +563,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
-
- if (slottime != phy->slottime) {
- phy->slottime = slottime;
-- mt7996_mac_set_timing(phy);
-+ mt7996_mcu_set_timing(phy, vif);
- }
- }
-
-@@ -904,7 +903,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
-
- mutex_lock(&dev->mt76.mutex);
- phy->coverage_class = max_t(s16, coverage_class, 0);
-- mt7996_mac_set_timing(phy);
-+ mt7996_mac_set_coverage_class(phy);
- mutex_unlock(&dev->mt76.mutex);
- }
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6706d38c..0ede9769 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -701,6 +701,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif,
- sizeof(req), true);
- }
-
-+static void
-+mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
-+{
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct mt7996_phy *phy = mvif->phy;
-+ struct bss_ifs_time_tlv *ifs_time;
-+ struct tlv *tlv;
-+ bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
-+
-+ tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time));
-+
-+ ifs_time = (struct bss_ifs_time_tlv *)tlv;
-+ ifs_time->slot_valid = true;
-+ ifs_time->sifs_valid = true;
-+ ifs_time->rifs_valid = true;
-+ ifs_time->eifs_valid = true;
-+
-+ ifs_time->slot_time = cpu_to_le16(phy->slottime);
-+ ifs_time->sifs_time = cpu_to_le16(10);
-+ ifs_time->rifs_time = cpu_to_le16(2);
-+ ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84);
-+
-+ if (is_2ghz) {
-+ ifs_time->eifs_cck_valid = true;
-+ ifs_time->eifs_cck_time = cpu_to_le16(314);
-+ }
-+}
-+
- static int
- mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- struct ieee80211_vif *vif,
-@@ -826,6 +854,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
- mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
- mt7996_mcu_bss_ra_tlv(skb, vif, phy);
- mt7996_mcu_bss_txcmd_tlv(skb, true);
-+ mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
-
- if (vif->bss_conf.he_support)
- mt7996_mcu_bss_he_tlv(skb, vif, phy);
-@@ -838,6 +867,23 @@ out:
- MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
- }
-
-+int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
-+{
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct mt7996_dev *dev = phy->dev;
-+ struct sk_buff *skb;
-+
-+ skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
-+ MT7996_BSS_UPDATE_MAX_SIZE);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
-+
-+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+ MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
-+}
-+
- static int
- mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
- struct ieee80211_ampdu_params *params,
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index d7075a4d..078f8285 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -317,6 +317,22 @@ struct bss_sec_tlv {
- u8 __rsv2[1];
- } __packed;
-
-+struct bss_ifs_time_tlv {
-+ __le16 tag;
-+ __le16 len;
-+ u8 slot_valid;
-+ u8 sifs_valid;
-+ u8 rifs_valid;
-+ u8 eifs_valid;
-+ __le16 slot_time;
-+ __le16 sifs_time;
-+ __le16 rifs_time;
-+ __le16 eifs_time;
-+ u8 eifs_cck_valid;
-+ u8 rsv;
-+ __le16 eifs_cck_time;
-+} __packed;
-+
- struct bss_power_save {
- __le16 tag;
- __le16 len;
-@@ -552,6 +568,7 @@ enum {
- sizeof(struct bss_txcmd_tlv) + \
- sizeof(struct bss_power_save) + \
- sizeof(struct bss_sec_tlv) + \
-+ sizeof(struct bss_ifs_time_tlv) + \
- sizeof(struct bss_mld_tlv))
-
- #define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 7dfdc738..42892f06 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -463,6 +463,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
- const struct mt7996_dfs_pattern *pattern);
- int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
- int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
-+int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
- int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
- int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
- u8 rx_sel, u8 val);
-@@ -526,7 +527,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, int pid,
- enum mt76_txq_id qid, u32 changed);
--void mt7996_mac_set_timing(struct mt7996_phy *phy);
-+void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
- int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
similarity index 67%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
index 6864e26..873029f 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
@@ -1,7 +1,7 @@
-From 18ed969cf7bfdaa059ed946f5bacd62a2ebf9ffe Mon Sep 17 00:00:00 2001
+From 3fdeeee1f24b09fc0d08b6a386e06c6146e83d9c Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Tue, 23 May 2023 15:49:03 +0800
-Subject: [PATCH 35/39] wifi: mt76: mt7996: make band capability init flexible
+Subject: [PATCH 07/98] wifi: mt76: mt7996: make band capability init flexible
There're some variations of mt7996 chipset which only support two-band,
so parse the adie combination to correctly set band capability.
@@ -9,20 +9,20 @@
Change-Id: Ifcb49504f02f5cc6a23c626e30b4f0e1360fe157
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
- mt7996/dma.c | 8 ++++----
+ mt7996/dma.c | 14 +++++++-------
mt7996/init.c | 29 ++++++++++++++++++-----------
mt7996/mcu.c | 13 +++++--------
mt7996/mt7996.h | 11 +++++++++++
mt7996/regs.h | 3 +++
- 5 files changed, 41 insertions(+), 23 deletions(-)
+ 5 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 6a21e3e..f01cea5 100644
+index 2221d22..3d04470 100644
--- a/mt7996/dma.c
+++ b/mt7996/dma.c
-@@ -159,13 +159,13 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
-
- irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
+@@ -222,13 +222,13 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ /* enable interrupts for TX/RX rings */
+ irq_mask = MT_INT_MCU_CMD | MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
- if (!dev->mphy.band_idx)
+ if (mt7996_band_valid(dev, MT_BAND0))
@@ -36,23 +36,50 @@
+ if (mt7996_band_valid(dev, MT_BAND2))
irq_mask |= MT_INT_BAND2_RX_DONE;
- done:
-@@ -334,7 +334,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (mtk_wed_device_active(wed) && wed_reset) {
+@@ -354,7 +354,7 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
if (ret)
return ret;
+- if (dev->dbdc_support) {
++ if (mt7996_band_valid(dev, MT_BAND1)) {
+ /* rx msdu page queue for band1 */
+ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags =
+ MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN;
+@@ -368,7 +368,7 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
+ return ret;
+ }
+
+- if (dev->tbtc_support) {
++ if (mt7996_band_valid(dev, MT_BAND2)) {
+ /* rx msdu page queue for band2 */
+ mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags =
+ MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN;
+@@ -488,7 +488,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
- if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
+ if (mt7996_band_valid(dev, MT_BAND2)) {
/* rx data queue for band2 */
+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
- MT_RXQ_ID(MT_RXQ_BAND2),
+@@ -542,7 +542,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
+- if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
++ if (mt7996_band_valid(dev, MT_BAND2)) {
+ /* rx rro data queue for band2 */
+ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
+ MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
diff --git a/mt7996/init.c b/mt7996/init.c
-index 0562439..0825e0b 100644
+index de4a5f7..2e6efc5 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -529,11 +529,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
- u32 mac_ofs, hif1_ofs = 0;
+@@ -539,11 +539,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
int ret;
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
- if (band != MT_BAND1 && band != MT_BAND2)
- return 0;
@@ -63,7 +90,7 @@
return 0;
if (phy)
-@@ -648,8 +644,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -782,8 +778,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
INIT_WORK(&dev->init_work, mt7996_init_work);
@@ -76,7 +103,7 @@
ret = mt7996_dma_init(dev);
if (ret)
-@@ -1089,8 +1087,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1217,8 +1215,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
@@ -85,7 +112,7 @@
ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
if (ret)
return ret;
-@@ -1099,13 +1095,24 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1227,13 +1223,24 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
@@ -113,7 +140,7 @@
void mt7996_unregister_device(struct mt7996_dev *dev)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index c647979..9fb800a 100644
+index 8320c8c..84f362b 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -2767,7 +2767,7 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
@@ -144,10 +171,10 @@
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WM_UNI_CMD(VOW), true);
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index f59dce7..488f59c 100644
+index e1972e9..137d5a2 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -431,6 +431,17 @@ mt7996_phy3(struct mt7996_dev *dev)
+@@ -381,6 +381,17 @@ mt7996_phy3(struct mt7996_dev *dev)
return __mt7996_phy(dev, MT_BAND2);
}
@@ -166,10 +193,10 @@
extern struct pci_driver mt7996_pci_driver;
extern struct pci_driver mt7996_hif_driver;
diff --git a/mt7996/regs.h b/mt7996/regs.h
-index c054586..3a5914c 100644
+index 854390d..a4d5ad8 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
-@@ -546,6 +546,9 @@ enum base_rev {
+@@ -602,6 +602,9 @@ enum base_rev {
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
similarity index 82%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
index 5dc8109..a5b808a 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
@@ -1,7 +1,7 @@
-From de92f88f5c00cf1069df00bb89f50281b0b2d05e Mon Sep 17 00:00:00 2001
+From 8f93c158b307ee75e622a5897499f5837c0d3446 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 12 May 2023 16:24:53 +0800
-Subject: [PATCH 37/39] wifi: mt76: mt7996: add beacon duplicate tx mode
+Subject: [PATCH 08/98] wifi: mt76: mt7996: add beacon duplicate tx mode
support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -16,22 +16,22 @@
7 files changed, 69 insertions(+), 25 deletions(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index bfec420..4bb9508 100644
+index 99077f1..90c08d2 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1224,6 +1224,7 @@ enum {
+@@ -1239,6 +1239,7 @@ enum {
MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
MCU_UNI_CMD_THERMAL = 0x35,
MCU_UNI_CMD_VOW = 0x37,
+ MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
- MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+ MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
diff --git a/mt7996/init.c b/mt7996/init.c
-index 1072874..9eba689 100644
+index 2e6efc5..17a4abd 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -351,6 +351,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+@@ -354,6 +354,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
phy->slottime = 9;
@@ -39,7 +39,7 @@
hw->sta_data_size = sizeof(struct mt7996_sta);
hw->vif_data_size = sizeof(struct mt7996_vif);
-@@ -459,11 +460,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+@@ -463,11 +464,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
u16 rate = mt76_rates[i].hw_value;
@@ -55,10 +55,10 @@
}
diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 724af82..05269e7 100644
+index 4be5410..6688186 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -252,17 +252,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+@@ -248,17 +248,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
mt76_clear(dev, addr, BIT(5));
}
@@ -73,15 +73,15 @@
- mt76_wr(dev, MT_WTBL_ITCR, ctrl);
-}
-
- static void
- mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
- struct ieee80211_radiotap_he *he,
+ /* The HW does not translate the mac header to 802.3 for mesh point */
+ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
+ {
diff --git a/mt7996/main.c b/mt7996/main.c
-index 20b89a7..2ed66e6 100644
+index 280120b..41f0fa1 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
-@@ -544,24 +544,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+@@ -522,24 +522,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt76_phy *mphy = hw->priv;
u16 rate;
- u8 i, idx, ht;
@@ -101,7 +101,7 @@
+ mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);
- /* must odd index */
-- idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
+- idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
- mt7996_mac_set_fixed_rate_table(dev, idx, rate);
return idx;
}
@@ -114,7 +114,7 @@
return mvif->basic_rates_idx;
}
-@@ -965,7 +966,6 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+@@ -966,7 +967,6 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
mt7996_set_stream_vht_txbf_caps(phy);
mt7996_set_stream_he_eht_caps(phy);
@@ -123,10 +123,10 @@
return 0;
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index a5c473a..b34c6b7 100644
+index 84f362b..dbb3ceb 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -4056,6 +4056,36 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+@@ -4055,6 +4055,36 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
@@ -164,10 +164,10 @@
{
struct {
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index eb63441..e32767e 100644
+index f1528df..c20a947 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -771,4 +771,24 @@ enum {
+@@ -738,4 +738,24 @@ enum {
#define MT7996_SEC_KEY_IDX GENMASK(2, 1)
#define MT7996_SEC_IV BIT(3)
@@ -193,10 +193,10 @@
+
#endif
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index f78f1fd..286fc1e 100644
+index 137d5a2..21ad51d 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -48,7 +48,7 @@
+@@ -47,7 +47,7 @@
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
@@ -205,7 +205,7 @@
#define MT7996_BEACON_RATES_TBL 25
#define MT7996_THERMAL_THROTTLE_MAX 100
-@@ -256,6 +256,8 @@ struct mt7996_phy {
+@@ -213,6 +213,8 @@ struct mt7996_phy {
u8 rdd_state;
@@ -214,7 +214,7 @@
u32 rx_ampdu_ts;
u32 ampdu_ref;
-@@ -539,6 +541,8 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+@@ -475,6 +477,8 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val);
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
struct cfg80211_chan_def *chandef);
@@ -223,7 +223,7 @@
int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
-@@ -606,8 +610,6 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
+@@ -539,8 +543,6 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable);
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch
deleted file mode 100644
index 24d2bfd..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 9cf96fa56a20d30f7e46e96d9c48c3568fbf11af Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Tue, 7 Mar 2023 17:05:01 +0800
-Subject: [PATCH 08/11] wifi: mt76: mt7996: use correct phy for background
- radar event
-
-If driver directly uses the band_idx reported from the radar event to
-access mt76_phy array, it will get the wrong phy for background radar.
-Fix this by adjusting the statement.
-
-Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/mcu.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 0ede9769..20519bff 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
- if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
- return;
-
-- mphy = dev->mt76.phys[r->band_idx];
-+ if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
-+ mphy = dev->rdd2_phy->mt76;
-+ else
-+ mphy = dev->mt76.phys[r->band_idx];
-+
- if (!mphy)
- return;
-
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch
deleted file mode 100644
index 6ffa018..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From f9ac23ac488c0dafceab97c8d39a22904cf78f77 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Thu, 23 Mar 2023 15:16:14 +0800
-Subject: [PATCH 09/11] wifi: mt76: mt7996: fix WA event ring size
-
-Fix rx ring size of WA event to get rid of event loss and queue overflow
-problems.
-
-Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/dma.c | 2 +-
- mt7996/mt7996.h | 1 +
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 53414346..fbedaacf 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -293,7 +293,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- /* event from WA */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
- MT_RXQ_ID(MT_RXQ_MCU_WA),
-- MT7996_RX_MCU_RING_SIZE,
-+ MT7996_RX_MCU_RING_SIZE_WA,
- MT_RX_BUF_SIZE,
- MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
- if (ret)
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 42892f06..a3bd85d3 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -26,6 +26,7 @@
-
- #define MT7996_RX_RING_SIZE 1536
- #define MT7996_RX_MCU_RING_SIZE 512
-+#define MT7996_RX_MCU_RING_SIZE_WA 1024
-
- #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
- #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
similarity index 76%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
index c2fed58..b151c94 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
@@ -1,7 +1,7 @@
-From affb48f4b09fca1e4df1e2291c78ee01b877e40f Mon Sep 17 00:00:00 2001
+From 3e4d68091c7b74769481acdf1b305fd1edb15d4d Mon Sep 17 00:00:00 2001
From: "sujuan.chen" <sujuan.chen@mediatek.com>
Date: Tue, 30 May 2023 11:27:01 +0800
-Subject: [PATCH 39/39] wifi: mt76: mt7996: fix bss rate tlv to sync firmware
+Subject: [PATCH 09/98] wifi: mt76: mt7996: fix bss rate tlv to sync firmware
change
Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
@@ -10,7 +10,7 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index e32767e..549007f 100644
+index c20a947..78ecd75 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -259,7 +259,7 @@ struct bss_rate_tlv {
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch
deleted file mode 100644
index c0f61b7..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From 8a284ffc268754a8e941888ce6f1b506f3c7564c Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
-Date: Mon, 28 Nov 2022 14:36:09 +0800
-Subject: [PATCH 10/11] wifi: mt76: mt7996: add muru support
-
-Add sta_rec_muru() fw command to support MU-MIMO and OFDMA features.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt76_connac_mcu.h | 3 ++-
- mt7996/mcu.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 57 insertions(+), 2 deletions(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index b91262ee..6249de57 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -519,7 +519,8 @@ struct sta_rec_muru {
- u8 uo_ra;
- u8 he_2x996_tone;
- u8 rx_t_frame_11ac;
-- u8 rsv[3];
-+ u8 rx_ctrl_frame_to_mbss;
-+ u8 rsv[2];
- } ofdma_ul;
-
- struct {
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 20519bff..611f6450 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -1101,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
- }
- }
-
-+static void
-+mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
-+ struct ieee80211_vif *vif, struct ieee80211_sta *sta)
-+{
-+ struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
-+ struct sta_rec_muru *muru;
-+ struct tlv *tlv;
-+
-+ if (vif->type != NL80211_IFTYPE_STATION &&
-+ vif->type != NL80211_IFTYPE_AP)
-+ return;
-+
-+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
-+
-+ muru = (struct sta_rec_muru *)tlv;
-+ muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
-+ vif->bss_conf.he_mu_beamformer ||
-+ vif->bss_conf.vht_mu_beamformer ||
-+ vif->bss_conf.vht_mu_beamformee;
-+ muru->cfg.ofdma_dl_en = true;
-+
-+ if (sta->deflink.vht_cap.vht_supported)
-+ muru->mimo_dl.vht_mu_bfee =
-+ !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
-+
-+ if (!sta->deflink.he_cap.has_he)
-+ return;
-+
-+ muru->mimo_dl.partial_bw_dl_mimo =
-+ HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);
-+
-+ muru->mimo_ul.full_ul_mimo =
-+ HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);
-+ muru->mimo_ul.partial_ul_mimo =
-+ HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
-+
-+ muru->ofdma_dl.punc_pream_rx =
-+ HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
-+ muru->ofdma_dl.he_20m_in_40m_2g =
-+ HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]);
-+ muru->ofdma_dl.he_20m_in_160m =
-+ HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
-+ muru->ofdma_dl.he_80m_in_160m =
-+ HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
-+
-+ muru->ofdma_ul.t_frame_dur =
-+ HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
-+ muru->ofdma_ul.mu_cascading =
-+ HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
-+ muru->ofdma_ul.uo_ra =
-+ HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
-+}
-+
- static inline bool
- mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, bool bfee)
-@@ -1778,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- mt7996_mcu_sta_he_6g_tlv(skb, sta);
- /* starec eht */
- mt7996_mcu_sta_eht_tlv(skb, sta);
-- /* TODO: starec muru */
-+ /* starec muru */
-+ mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta);
- /* starec bfee */
- mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
- /* starec hdr trans */
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0041-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
similarity index 76%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0041-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
index f6e14b7..ca966b6 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0041-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
@@ -1,7 +1,7 @@
-From 78bc83a6a4dc69f135c6a32756e8acb96c64b1bf Mon Sep 17 00:00:00 2001
+From e1ddb78f4185559bc6f9be1d1b302f9f52899f94 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Tue, 13 Jun 2023 09:04:43 +0800
-Subject: [PATCH] wifi: mt76: mt7996: adjust wfdma setting to enhance
+Subject: [PATCH 10/98] wifi: mt76: mt7996: adjust wfdma setting to enhance
throughput
1. Set band 1 traffic to pcie1.
@@ -10,15 +10,15 @@
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
---
- mt7996/dma.c | 57 ++++++++++++++++++++++++++++++++++++++-------------
- mt7996/regs.h | 9 ++++++++
- 2 files changed, 52 insertions(+), 14 deletions(-)
+ mt7996/dma.c | 70 +++++++++++++++++++++++++++++++++++----------------
+ mt7996/regs.h | 9 +++++++
+ 2 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/mt7996/dma.c b/mt7996/dma.c
-index f01cea5e..bb390517 100644
+index 3d04470..1ed91da 100644
--- a/mt7996/dma.c
+++ b/mt7996/dma.c
-@@ -56,22 +56,34 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+@@ -99,38 +99,49 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7996_TXQ_FWDL);
}
@@ -62,11 +62,33 @@
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x2));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x10));
-+#undef PREFETCH
- mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
- }
-@@ -223,6 +235,12 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ if (dev->has_rro) {
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
+- PREFETCH(0x3a0, 0x10));
++ PREFETCH(0x10));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
+- PREFETCH(0x4a0, 0x10));
++ PREFETCH(0x10));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
+- PREFETCH(0x5a0, 0x4));
++ PREFETCH(0x4));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
+- PREFETCH(0x5e0, 0x4));
++ PREFETCH(0x4));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
+- PREFETCH(0x620, 0x4));
++ PREFETCH(0x4));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
+- PREFETCH(0x660, 0x4));
++ PREFETCH(0x4));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
+- PREFETCH(0x6a0, 0x4));
++ PREFETCH(0x4));
+ }
+ #undef PREFETCH
+
+@@ -295,6 +306,12 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1,
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
@@ -79,7 +101,7 @@
if (dev->hif2) {
/* GLO_CFG_EXT0 */
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
-@@ -234,7 +252,18 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+@@ -306,7 +323,18 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
@@ -100,10 +122,10 @@
if (dev->hif2) {
diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 3a5914c4..5917ba1a 100644
+index a4d5ad8..f7c99cd 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
-@@ -333,6 +333,11 @@ enum base_rev {
+@@ -366,6 +366,11 @@ enum base_rev {
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
@@ -115,7 +137,7 @@
#define WF_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD BIT(18)
#define WF_WFDMA0_GLO_CFG_EXT0_WED_MERGE_MODE BIT(14)
-@@ -355,10 +360,14 @@ enum base_rev {
+@@ -388,10 +393,14 @@ enum base_rev {
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch
new file mode 100644
index 0000000..d32dea5
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch
@@ -0,0 +1,46 @@
+From bae9e0c386cd710bdf414b0e0e097ea95812673e Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Wed, 6 Sep 2023 14:51:00 +0800
+Subject: [PATCH 11/98] wifi: mt76: mt7996: fill txd bandwidth filed value for
+ fixed rate frame
+
+Fill bw field value for fixed rate enabled frame to keep it be sent by bw20.
+Without this change, the bw of fixed rate enabled frame will be decided
+by hardware.
+
+Reported-by: Chank Chen <chank.chen@mediatek.com>
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt76_connac3_mac.h | 1 +
+ mt7996/mac.c | 3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/mt76_connac3_mac.h b/mt76_connac3_mac.h
+index 87bfa44..df6b02a 100644
+--- a/mt76_connac3_mac.h
++++ b/mt76_connac3_mac.h
+@@ -239,6 +239,7 @@ enum tx_mgnt_type {
+
+ #define MT_TXD6_TX_SRC GENMASK(31, 30)
+ #define MT_TXD6_VTA BIT(28)
++#define MT_TXD6_FIXED_BW BIT(25)
+ #define MT_TXD6_BW GENMASK(25, 22)
+ #define MT_TXD6_TX_RATE GENMASK(21, 16)
+ #define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 6688186..2c6bee4 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -943,7 +943,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ idx = mvif->basic_rates_idx;
+ }
+
+- txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
++ val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
++ txwi[6] |= cpu_to_le32(val);
+ txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
+ }
+ }
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch
deleted file mode 100644
index aa039ce..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 0cc8d7827510e36978175d84d63cced5f842ff61 Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Mon, 17 Apr 2023 09:49:53 +0800
-Subject: [PATCH 11/11] wifi: mt76: mt7996: increase tx token size
-
-Align tx token size to proprietary driver, which can improve peak
-throughput under MU performance tests.
-
-Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/mt7996.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index a3bd85d3..651f53aa 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -36,7 +36,7 @@
- #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
- #define MT7996_EEPROM_SIZE 7680
- #define MT7996_EEPROM_BLOCK_SIZE 16
--#define MT7996_TOKEN_SIZE 8192
-+#define MT7996_TOKEN_SIZE 16384
-
- #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
- #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch
new file mode 100644
index 0000000..3a49f34
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch
@@ -0,0 +1,72 @@
+From 2d7f3506aa6759fa1a7667d53bf88eb543035c33 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 24 Jul 2023 16:32:03 +0800
+Subject: [PATCH 12/98] wifi: mt76: mt7996: add IEEE80211_RC_SMPS_CHANGED
+ handler
+
+Send mcu command to firmware to handle smps mode.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mac.c | 4 +++-
+ mt7996/mcu.c | 8 +++++---
+ mt7996/mt7996.h | 2 ++
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 2c6bee4..ccb7b22 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2222,7 +2222,9 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
+ IEEE80211_RC_BW_CHANGED))
+ mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
+
+- /* TODO: smps change */
++ if (changed & IEEE80211_RC_SMPS_CHANGED)
++ mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
++ RATE_PARAM_MMPS_UPDATE);
+
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ }
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index dbb3ceb..18c3f34 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1679,9 +1679,8 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
+ MCU_WM_UNI_CMD(RA), true);
+ }
+
+-static int
+-mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+- struct ieee80211_sta *sta, void *data, u32 field)
++int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++ struct ieee80211_sta *sta, void *data, u32 field)
+ {
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+@@ -1709,6 +1708,9 @@ mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ if (phy)
+ ra->phy = *phy;
+ break;
++ case RATE_PARAM_MMPS_UPDATE:
++ ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
++ break;
+ default:
+ break;
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 21ad51d..c8e7a33 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -451,6 +451,8 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, bool changed);
+ int mt7996_set_channel(struct mt7996_phy *phy);
++int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++ struct ieee80211_sta *sta, void *data, u32 field);
+ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
+ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif);
+ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch
new file mode 100644
index 0000000..5f85886
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch
@@ -0,0 +1,154 @@
+From 8c79e229decdc24af9e95e6396699b3723f7efc4 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 7 Jul 2023 10:35:05 +0800
+Subject: [PATCH 13/98] wifi: mt76: mt7996: fix mcu command format to align
+ firmware
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mcu.c | 12 ++++-----
+ mt7996/mcu.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 75 insertions(+), 8 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 18c3f34..ee1915c 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1684,8 +1684,8 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
+ {
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+- struct sta_phy *phy = data;
+- struct sta_rec_ra_fixed *ra;
++ struct sta_phy_uni *phy = data;
++ struct sta_rec_ra_fixed_uni *ra;
+ struct sk_buff *skb;
+ struct tlv *tlv;
+
+@@ -1696,7 +1696,7 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
+ return PTR_ERR(skb);
+
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
+- ra = (struct sta_rec_ra_fixed *)tlv;
++ ra = (struct sta_rec_ra_fixed_uni *)tlv;
+
+ switch (field) {
+ case RATE_PARAM_AUTO:
+@@ -1728,7 +1728,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
+ struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
+ struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
+ enum nl80211_band band = chandef->chan->band;
+- struct sta_phy phy = {};
++ struct sta_phy_uni phy = {};
+ int ret, nrates = 0;
+
+ #define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
+@@ -1816,13 +1816,13 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
+ struct cfg80211_chan_def *chandef = &mphy->chandef;
+ struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
+ enum nl80211_band band = chandef->chan->band;
+- struct sta_rec_ra *ra;
++ struct sta_rec_ra_uni *ra;
+ struct tlv *tlv;
+ u32 supp_rate = sta->deflink.supp_rates[band];
+ u32 cap = sta->wme ? STA_CAP_WMM : 0;
+
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
+- ra = (struct sta_rec_ra *)tlv;
++ ra = (struct sta_rec_ra_uni *)tlv;
+
+ ra->valid = true;
+ ra->auto_rate = true;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 78ecd75..05785cb 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -433,6 +433,73 @@ struct sta_rec_sec_uni {
+ struct sec_key_uni key[2];
+ } __packed;
+
++struct sta_phy_uni {
++ u8 type;
++ u8 flag;
++ u8 stbc;
++ u8 sgi;
++ u8 bw;
++ u8 ldpc;
++ u8 mcs;
++ u8 nss;
++ u8 he_ltf;
++ u8 rsv[3];
++};
++
++struct sta_rec_ra_uni {
++ __le16 tag;
++ __le16 len;
++
++ u8 valid;
++ u8 auto_rate;
++ u8 phy_mode;
++ u8 channel;
++ u8 bw;
++ u8 disable_cck;
++ u8 ht_mcs32;
++ u8 ht_gf;
++ u8 ht_mcs[4];
++ u8 mmps_mode;
++ u8 gband_256;
++ u8 af;
++ u8 auth_wapi_mode;
++ u8 rate_len;
++
++ u8 supp_mode;
++ u8 supp_cck_rate;
++ u8 supp_ofdm_rate;
++ __le32 supp_ht_mcs;
++ __le16 supp_vht_mcs[4];
++
++ u8 op_mode;
++ u8 op_vht_chan_width;
++ u8 op_vht_rx_nss;
++ u8 op_vht_rx_nss_type;
++
++ __le32 sta_cap;
++
++ struct sta_phy_uni phy;
++ u8 rx_rcpi[4];
++} __packed;
++
++struct sta_rec_ra_fixed_uni {
++ __le16 tag;
++ __le16 len;
++
++ __le32 field;
++ u8 op_mode;
++ u8 op_vht_chan_width;
++ u8 op_vht_rx_nss;
++ u8 op_vht_rx_nss_type;
++
++ struct sta_phy_uni phy;
++
++ u8 spe_idx;
++ u8 short_preamble;
++ u8 is_5g;
++ u8 mmps_mode;
++} __packed;
++
+ struct sta_rec_hdrt {
+ __le16 tag;
+ __le16 len;
+@@ -616,9 +683,9 @@ enum {
+ sizeof(struct sta_rec_amsdu) + \
+ sizeof(struct sta_rec_bfee) + \
+ sizeof(struct sta_rec_phy) + \
+- sizeof(struct sta_rec_ra) + \
++ sizeof(struct sta_rec_ra_uni) + \
+ sizeof(struct sta_rec_sec) + \
+- sizeof(struct sta_rec_ra_fixed) + \
++ sizeof(struct sta_rec_ra_fixed_uni) + \
+ sizeof(struct sta_rec_he_6g_capa) + \
+ sizeof(struct sta_rec_eht) + \
+ sizeof(struct sta_rec_hdrt) + \
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch
new file mode 100644
index 0000000..1a93d0b
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch
@@ -0,0 +1,170 @@
+From 6a8359a808df29b708b2fd2aa84c0a369be7a7d5 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Mon, 3 Jul 2023 22:38:43 +0800
+Subject: [PATCH 14/98] wifi: mt76: mt7996: add lock for indirect register
+ access
+
+Some races were observed during indirect register access, fix this
+by adding reg_lock and reworking l1/l2 remap flow.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I0de2cd27df9ccb7f9a7d9ce265e869175b1ca7f1
+---
+ mt7996/mmio.c | 69 +++++++++++++++++++++++++++++++++----------------
+ mt7996/mt7996.h | 3 +--
+ 2 files changed, 48 insertions(+), 24 deletions(-)
+
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index c7b6d4b..ab088a2 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -86,7 +86,6 @@ static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr)
+ u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
+ u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
+
+- dev->reg_l1_backup = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
+ dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
+ MT_HIF_REMAP_L1_MASK,
+ FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
+@@ -101,7 +100,6 @@ static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
+ u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
+ u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
+
+- dev->reg_l2_backup = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
+ dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2,
+ MT_HIF_REMAP_L2_MASK,
+ FIELD_PREP(MT_HIF_REMAP_L2_MASK, base));
+@@ -111,26 +109,10 @@ static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
+ return MT_HIF_REMAP_BASE_L2 + offset;
+ }
+
+-static void mt7996_reg_remap_restore(struct mt7996_dev *dev)
+-{
+- /* remap to ori status */
+- if (unlikely(dev->reg_l1_backup)) {
+- dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->reg_l1_backup);
+- dev->reg_l1_backup = 0;
+- }
+-
+- if (dev->reg_l2_backup) {
+- dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->reg_l2_backup);
+- dev->reg_l2_backup = 0;
+- }
+-}
+-
+ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
+ {
+ int i;
+
+- mt7996_reg_remap_restore(dev);
+-
+ if (addr < 0x100000)
+ return addr;
+
+@@ -147,6 +129,11 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
+ return dev->reg.map[i].mapped + ofs;
+ }
+
++ return 0;
++}
++
++static u32 __mt7996_reg_remap_addr(struct mt7996_dev *dev, u32 addr)
++{
+ if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
+ (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
+ (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
+@@ -171,28 +158,65 @@ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
+ {
+ u32 addr = __mt7996_reg_addr(dev, offset);
+
+- memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ unsigned long flags;
++
++ if (addr) {
++ memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ return;
++ }
++
++ spin_lock_irqsave(&dev->reg_lock, flags);
++ memcpy_fromio(buf, dev->mt76.mmio.regs +
++ __mt7996_reg_remap_addr(dev, offset), len);
++ spin_unlock_irqrestore(&dev->reg_lock, flags);
+ }
+
+ static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset), val;
++ unsigned long flags;
++
++ if (addr)
++ return dev->bus_ops->rr(mdev, addr);
+
+- return dev->bus_ops->rr(mdev, __mt7996_reg_addr(dev, offset));
++ spin_lock_irqsave(&dev->reg_lock, flags);
++ val = dev->bus_ops->rr(mdev, __mt7996_reg_remap_addr(dev, offset));
++ spin_unlock_irqrestore(&dev->reg_lock, flags);
++
++ return val;
+ }
+
+ static void mt7996_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset);
++ unsigned long flags;
+
+- dev->bus_ops->wr(mdev, __mt7996_reg_addr(dev, offset), val);
++ if (addr) {
++ dev->bus_ops->wr(mdev, addr, val);
++ return;
++ }
++
++ spin_lock_irqsave(&dev->reg_lock, flags);
++ dev->bus_ops->wr(mdev, __mt7996_reg_remap_addr(dev, offset), val);
++ spin_unlock_irqrestore(&dev->reg_lock, flags);
+ }
+
+ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset);
++ unsigned long flags;
++
++ if (addr)
++ return dev->bus_ops->rmw(mdev, addr, mask, val);
++
++ spin_lock_irqsave(&dev->reg_lock, flags);
++ val = dev->bus_ops->rmw(mdev, __mt7996_reg_remap_addr(dev, offset), mask, val);
++ spin_unlock_irqrestore(&dev->reg_lock, flags);
+
+- return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
++ return val;
+ }
+
+ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+@@ -341,6 +365,7 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
+
+ dev = container_of(mdev, struct mt7996_dev, mt76);
+ mt76_mmio_init(&dev->mt76, mem_base);
++ spin_lock_init(&dev->reg_lock);
+
+ switch (device_id) {
+ case 0x7990:
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index c8e7a33..c0ceef0 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -309,8 +309,7 @@ struct mt7996_dev {
+ u8 n_agrt;
+ } twt;
+
+- u32 reg_l1_backup;
+- u32 reg_l2_backup;
++ spinlock_t reg_lock;
+
+ u8 wtbl_size_group;
+ };
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch
deleted file mode 100644
index 8103127..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 5e2177e77b9609185f748708332aa6a6fdf4d1f9 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 6 Mar 2023 15:52:26 +0800
-Subject: [PATCH 14/39] wifi: mt76: mt7996: set wcid in txp
-
-Set correct wcid in txp for SDO to get wtbl.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Change-Id: Ie715a659ff52f2d85332158f273d0ee4fe9f4051
----
- mt7996/mac.c | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 2da61d2..bddb84f 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1166,10 +1166,12 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- }
-
- txp->fw.token = cpu_to_le16(id);
-- if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
-- txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
-- else
-+ if ((is_8023 && is_multicast_ether_addr(tx_info->skb->data)) ||
-+ (!is_8023 && is_multicast_ether_addr(hdr->addr1)))
- txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
-+ else
-+ txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
-+
- tx_info->skb = DMA_DUMMY_DATA;
-
- /* pass partial skb header to fw */
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
similarity index 77%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
index e6a4f75..381c929 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
@@ -1,7 +1,7 @@
-From eec83d4410d7c669d9a05bba1a69a742a6ccd490 Mon Sep 17 00:00:00 2001
+From 09a1b2d9ad49d3bea1bdd8d4f7326af6a65a3dbb Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 16 Feb 2023 13:53:14 +0800
-Subject: [PATCH 16/39] wifi: mt76: connac: set correct muar_idx for connac3
+Subject: [PATCH 15/98] wifi: mt76: connac: set correct muar_idx for connac3
chipset
Set the muar_idx to 0xe for the hw bcast/mcast station entry of connac3
@@ -15,10 +15,10 @@
2 files changed, 8 insertions(+)
diff --git a/mt76_connac.h b/mt76_connac.h
-index 77ca8f0..02acac6 100644
+index e5ebde1..c6726ab 100644
--- a/mt76_connac.h
+++ b/mt76_connac.h
-@@ -240,6 +240,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
+@@ -245,6 +245,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
}
@@ -31,10 +31,10 @@
{
switch (mt76_chip(dev)) {
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 46f69aa..5fab677 100644
+index bcd6c20..68de525 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
-@@ -281,6 +281,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
+@@ -282,6 +282,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
};
struct sk_buff *skb;
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
deleted file mode 100644
index ea01cf0..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 5580f05c864aadfad4092fc97a937869dc08eca8 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Thu, 16 Feb 2023 00:39:01 +0800
-Subject: [PATCH 15/39] wifi: mt76: mt7996: reduce repeated bss_info and
- sta_rec commands
-
-Refine the flow of setting bss_info and sta_rec commands to prevent from
-sending duplicated commands, especially for station mode.
-
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: Iffd2c81f9ec98284793e75f4b7d39e9618977024
----
- mt7996/main.c | 21 ++++++---------------
- 1 file changed, 6 insertions(+), 15 deletions(-)
-
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 786c3fb..02a33b8 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -248,8 +248,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
- struct mt7996_phy *phy = mt7996_hw_phy(hw);
- int idx = msta->wcid.idx;
-
-- mt7996_mcu_add_bss_info(phy, vif, false);
- mt7996_mcu_add_sta(dev, vif, NULL, false);
-+ mt7996_mcu_add_bss_info(phy, vif, false);
-
- if (vif == phy->monitor_vif)
- phy->monitor_vif = NULL;
-@@ -544,17 +544,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
- /* station mode uses BSSID to map the wlan entry to a peer,
- * and then peer references bss_info_rfch to set bandwidth cap.
- */
-- if (changed & BSS_CHANGED_BSSID &&
-- vif->type == NL80211_IFTYPE_STATION) {
-- bool join = !is_zero_ether_addr(info->bssid);
--
-- mt7996_mcu_add_bss_info(phy, vif, join);
-- mt7996_mcu_add_sta(dev, vif, NULL, join);
-+ if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
-+ (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
-+ (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
-+ mt7996_mcu_add_bss_info(phy, vif, true);
-+ mt7996_mcu_add_sta(dev, vif, NULL, true);
- }
-
-- if (changed & BSS_CHANGED_ASSOC)
-- mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
--
- if (changed & BSS_CHANGED_ERP_CTS_PROT)
- mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
-
-@@ -575,11 +571,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
- mvif->basic_rates_idx =
- mt7996_get_rates_table(hw, vif, false, false);
-
-- if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
-- mt7996_mcu_add_bss_info(phy, vif, true);
-- mt7996_mcu_add_sta(dev, vif, NULL, true);
-- }
--
- /* ensure that enable txcmd_mode after bss_info */
- if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
- mt7996_mcu_set_tx(dev, vif);
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
index 3d4d1c0..a850a6c 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
@@ -1,7 +1,7 @@
-From cf66e6fc90e7a12209bd0a3d9b687b37f7324718 Mon Sep 17 00:00:00 2001
+From 4d055393b680ce616cb96f75cca154016cfb9a68 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Fri, 19 May 2023 14:16:50 +0800
-Subject: [PATCH] wifi: mt76: mt7996: add firmware WA's coredump.
+Subject: [PATCH 16/98] wifi: mt76: mt7996: add firmware WA's coredump.
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Change-Id: I51f115b4ae15bc0f871f93652570d72511dbf880
@@ -15,7 +15,7 @@
6 files changed, 182 insertions(+), 83 deletions(-)
diff --git a/mt7996/coredump.c b/mt7996/coredump.c
-index ccab0d7b..60b88085 100644
+index ccab0d7..60b8808 100644
--- a/mt7996/coredump.c
+++ b/mt7996/coredump.c
@@ -7,11 +7,11 @@
@@ -336,7 +336,7 @@
}
diff --git a/mt7996/coredump.h b/mt7996/coredump.h
-index af2ba219..01ed3731 100644
+index af2ba21..01ed373 100644
--- a/mt7996/coredump.h
+++ b/mt7996/coredump.h
@@ -6,10 +6,13 @@
@@ -429,10 +429,10 @@
return NULL;
}
diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 986031f5..724af82a 100644
+index ccb7b22..066955e 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -2082,28 +2082,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
+@@ -1962,28 +1962,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
}
/* firmware coredump */
@@ -465,7 +465,7 @@
if (!mem_region || !crash_data->memdump_buf_len) {
mutex_unlock(&dev->dump_mutex);
goto skip_memdump;
-@@ -2113,6 +2110,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -1993,6 +1990,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
buf_len = crash_data->memdump_buf_len;
/* dumping memory content... */
@@ -475,7 +475,7 @@
memset(buf, 0, buf_len);
for (i = 0; i < num; i++) {
if (mem_region->len > buf_len) {
-@@ -2129,6 +2129,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2009,6 +2009,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
mt7996_memcpy_fromio(dev, buf, mem_region->start,
mem_region->len);
@@ -483,7 +483,7 @@
hdr->start = mem_region->start;
hdr->len = mem_region->len;
-@@ -2145,8 +2146,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2025,8 +2026,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
mutex_unlock(&dev->dump_mutex);
skip_memdump:
@@ -507,7 +507,7 @@
}
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 38292da3..14f7a43f 100644
+index ee1915c..2c611e7 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -2458,6 +2458,8 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
@@ -530,27 +530,27 @@
fw_type, hdr->fw_ver, hdr->build_date);
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 561c1cdc..f59dce77 100644
+index c0ceef0..0bb20a9 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -58,6 +58,8 @@
+@@ -57,6 +57,8 @@
#define MT7996_CRIT_TEMP 110
#define MT7996_MAX_TEMP 120
+#define MT7996_BUILD_TIME_LEN 24
+
- struct mt7996_vif;
- struct mt7996_sta;
- struct mt7996_dfs_pulse;
-@@ -68,6 +70,7 @@ enum mt7996_ram_type {
- MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
+ #define MT7996_RRO_MAX_SESSION 1024
+ #define MT7996_RRO_WINDOW_MAX_LEN 1024
+ #define MT7996_RRO_ADDR_ELEM_LEN 128
+@@ -82,6 +84,7 @@ enum mt7996_ram_type {
+ MT7996_RAM_TYPE_WM,
MT7996_RAM_TYPE_WA,
MT7996_RAM_TYPE_DSP,
+ __MT7996_RAM_TYPE_MAX,
};
enum mt7996_txq_id {
-@@ -306,9 +309,11 @@ struct mt7996_dev {
+@@ -265,9 +268,11 @@ struct mt7996_dev {
struct mutex dump_mutex;
#ifdef CONFIG_DEV_COREDUMP
struct {
@@ -562,12 +562,12 @@
+ char ram_build_date[__MT7996_RAM_TYPE_MAX][MT7996_BUILD_TIME_LEN];
struct list_head sta_rc_list;
- struct list_head sta_poll_list;
+ struct list_head twt_list;
diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 86da1bf8..c054586d 100644
+index f7c99cd..bd0eb51 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
-@@ -482,7 +482,8 @@ enum base_rev {
+@@ -548,7 +548,8 @@ enum base_rev {
/* FW MODE SYNC */
#define MT_FW_ASSERT_CNT 0x02208274
@@ -577,7 +577,7 @@
#define MT_SWDEF_BASE 0x00401400
-@@ -580,11 +581,15 @@ enum base_rev {
+@@ -656,11 +657,15 @@ enum base_rev {
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
/* CONN MCU EXCP CON */
@@ -594,5 +594,5 @@
#endif
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch
new file mode 100644
index 0000000..54d32c3
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch
@@ -0,0 +1,107 @@
+From ff0611f9ade6ea4e9d84b7bd852ff745c609500b Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Wed, 28 Jun 2023 07:51:38 +0800
+Subject: [PATCH 17/98] wifi: mt76: mt7996: get tx_retries and tx_failed from
+ txfree for both wed on and wed off
+
+---
+ mt76_connac3_mac.h | 4 ++--
+ mt7996/mac.c | 21 ++++++++++++++++-----
+ mt7996/main.c | 6 ++++++
+ 3 files changed, 24 insertions(+), 7 deletions(-)
+
+diff --git a/mt76_connac3_mac.h b/mt76_connac3_mac.h
+index df6b02a..20a2fe9 100644
+--- a/mt76_connac3_mac.h
++++ b/mt76_connac3_mac.h
+@@ -272,11 +272,11 @@ enum tx_mgnt_type {
+ #define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
+ #define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
+
+-#define MT_TXFREE1_VER GENMASK(18, 16)
++#define MT_TXFREE1_VER GENMASK(19, 16)
+
+ #define MT_TXFREE_INFO_PAIR BIT(31)
+ #define MT_TXFREE_INFO_HEADER BIT(30)
+-#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
++#define MT_TXFREE_INFO_MLD_ID GENMASK(23, 12)
+ #define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
+ #define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
+ #define MT_TXFREE_INFO_STAT GENMASK(29, 28)
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 066955e..bdc90a0 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1119,6 +1119,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
+ struct mt76_txwi_cache *txwi;
+ struct ieee80211_sta *sta = NULL;
++ struct mt76_wcid *wcid;
+ LIST_HEAD(free_list);
+ struct sk_buff *skb, *tmp;
+ void *end = data + len;
+@@ -1137,7 +1138,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
+ }
+
+- if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
++ if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
+ return;
+
+ total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
+@@ -1153,10 +1154,9 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ info = le32_to_cpu(*cur_info);
+ if (info & MT_TXFREE_INFO_PAIR) {
+ struct mt7996_sta *msta;
+- struct mt76_wcid *wcid;
+ u16 idx;
+
+- idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
++ idx = FIELD_GET(MT_TXFREE_INFO_MLD_ID, info);
+ wcid = rcu_dereference(dev->mt76.wcid[idx]);
+ sta = wcid_to_sta(wcid);
+ if (!sta)
+@@ -1169,10 +1169,21 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ &mdev->sta_poll_list);
+ spin_unlock_bh(&mdev->sta_poll_lock);
+ continue;
+- }
++ } else if (info & MT_TXFREE_INFO_HEADER) {
++ u32 tx_retries = 0, tx_failed = 0;
++
++ if (!wcid)
++ continue;
++
++ tx_retries =
++ FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
++ tx_failed = tx_retries +
++ !!FIELD_GET(MT_TXFREE_INFO_STAT, info);
+
+- if (info & MT_TXFREE_INFO_HEADER)
++ wcid->stats.tx_retries += tx_retries;
++ wcid->stats.tx_failed += tx_failed;
+ continue;
++ }
+
+ for (i = 0; i < 2; i++) {
+ msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 41f0fa1..f152e76 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -997,6 +997,12 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
+ sinfo->txrate.flags = txrate->flags;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+
++ sinfo->tx_failed = msta->wcid.stats.tx_failed;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
++
++ sinfo->tx_retries = msta->wcid.stats.tx_retries;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
++
+ sinfo->ack_signal = (s8)msta->ack_signal;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch
new file mode 100644
index 0000000..5110644
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch
@@ -0,0 +1,249 @@
+From 63501a3e941097581dcee61a0149ee5bc944c579 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Wed, 28 Jun 2023 08:10:25 +0800
+Subject: [PATCH 18/98] wifi: mt76: mt7996: Add mcu commands for getting sta tx
+ statistic
+
+Per peer Tx/Rx statistic can only be obtained by querying WM when WED is
+on. This patch switches to periodic event reporting in the case of WED
+being enabled.
+---
+ mt76_connac_mcu.h | 15 +++++++++++
+ mt7996/mac.c | 5 ++++
+ mt7996/main.c | 15 +++++++++++
+ mt7996/mcu.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h | 26 ++++++++++++++++++
+ mt7996/mt7996.h | 1 +
+ 6 files changed, 130 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 90c08d2..e9dd9aa 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1023,6 +1023,8 @@ enum {
+ MCU_UNI_EVENT_TX_DONE = 0x2d,
+ MCU_UNI_EVENT_THERMAL = 0x35,
+ MCU_UNI_EVENT_NIC_CAPAB = 0x43,
++ MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
++ MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
+ };
+
+ #define MCU_UNI_CMD_EVENT BIT(1)
+@@ -1242,6 +1244,8 @@ enum {
+ MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
+ MCU_UNI_CMD_RRO = 0x57,
+ MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
++ MCU_UNI_CMD_PER_STA_INFO = 0x6d,
++ MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
+ MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
+ };
+
+@@ -1322,6 +1326,17 @@ enum {
+ UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
+ };
+
++enum UNI_ALL_STA_INFO_TAG {
++ UNI_ALL_STA_TX_RATE,
++ UNI_ALL_STA_TX_STAT,
++ UNI_ALL_STA_TXRX_ADM_STAT,
++ UNI_ALL_STA_TXRX_AIR_TIME,
++ UNI_ALL_STA_DATA_TX_RETRY_COUNT,
++ UNI_ALL_STA_GI_MODE,
++ UNI_ALL_STA_TXRX_MSDU_COUNT,
++ UNI_ALL_STA_MAX_NUM
++};
++
+ enum {
+ MT_NIC_CAP_TX_RESOURCE,
+ MT_NIC_CAP_TX_EFUSE_ADDR,
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index bdc90a0..4828f10 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2272,6 +2272,11 @@ void mt7996_mac_work(struct work_struct *work)
+ mphy->mac_work_count = 0;
+
+ mt7996_mac_update_stats(phy);
++
++ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
++ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
++ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
++ };
+ }
+
+ mutex_unlock(&mphy->dev->mutex);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index f152e76..e9e1fd9 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -977,6 +977,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ struct station_info *sinfo)
+ {
++ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+ struct rate_info *txrate = &msta->wcid.rate;
+
+@@ -1008,6 +1009,20 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
+
+ sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
++
++ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
++ sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
++
++ sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
++
++ sinfo->tx_packets = msta->wcid.stats.tx_packets;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
++
++ sinfo->rx_packets = msta->wcid.stats.rx_packets;
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
++ }
+ }
+
+ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 2c611e7..652a600 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -477,6 +477,54 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
+ phy->throttle_state = n->duty_percent;
+ }
+
++static void
++mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++ struct mt7996_mcu_all_sta_info_event *res;
++ u16 i;
++
++ skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
++
++ res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
++
++ for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
++ u8 ac;
++ u16 wlan_idx;
++ struct mt76_wcid *wcid;
++
++ switch (le16_to_cpu(res->tag)) {
++ case UNI_ALL_STA_TXRX_ADM_STAT:
++ wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
++ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
++
++ if (!wcid)
++ break;
++
++ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
++ wcid->stats.tx_bytes +=
++ le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
++ wcid->stats.rx_bytes +=
++ le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
++ }
++ break;
++ case UNI_ALL_STA_TXRX_MSDU_COUNT:
++ wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
++ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
++
++ if (!wcid)
++ break;
++
++ wcid->stats.tx_packets +=
++ le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
++ wcid->stats.rx_packets +=
++ le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
++ break;
++ default:
++ break;
++ }
++ }
++}
++
+ static void
+ mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -524,6 +572,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ case MCU_UNI_EVENT_THERMAL:
+ mt7996_mcu_rx_thermal_notify(dev, skb);
+ break;
++ case MCU_UNI_EVENT_ALL_STA_INFO:
++ mt7996_mcu_rx_all_sta_info_event(dev, skb);
++ break;
+ default:
+ break;
+ }
+@@ -4192,3 +4243,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
+ sizeof(req), true);
+ }
++
++int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
++{
++ struct mt7996_dev *dev = phy->dev;
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++ } __packed req = {
++ .tag = cpu_to_le16(tag),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ };
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
++ &req, sizeof(req), false);
++}
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 05785cb..97151d1 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -191,6 +191,32 @@ struct mt7996_mcu_thermal_notify {
+ u8 __rsv2[4];
+ } __packed;
+
++struct mt7996_mcu_all_sta_info_event {
++ u8 rsv[4];
++ __le16 tag;
++ __le16 len;
++ u8 more;
++ u8 rsv2;
++ __le16 sta_num;
++ u8 rsv3[2];
++
++ union {
++ struct {
++ __le16 wlan_idx;
++ u8 rsv[2];
++ __le32 tx_bytes[IEEE80211_NUM_ACS];
++ __le32 rx_bytes[IEEE80211_NUM_ACS];
++ } adm_stat[0];
++
++ struct {
++ __le16 wlan_idx;
++ u8 rsv[2];
++ __le32 tx_msdu_cnt;
++ __le32 rx_msdu_cnt;
++ } msdu_cnt[0];
++ };
++} __packed;
++
+ enum mt7996_chan_mib_offs {
+ UNI_MIB_OBSS_AIRTIME = 26,
+ UNI_MIB_NON_WIFI_TIME = 27,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 0bb20a9..420d113 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -494,6 +494,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
+ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ void mt7996_mcu_exit(struct mt7996_dev *dev);
++int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch
new file mode 100644
index 0000000..6505422
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch
@@ -0,0 +1,182 @@
+From 85c7ec658b8ea1ee4ca7525f21c28d2f456e0b95 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Wed, 28 Jun 2023 08:34:21 +0800
+Subject: [PATCH 19/98] wifi: mt76: mt7996: enable PPDU-TxS to host
+
+Enable PPDU-TxS by default no matter WED on or WED off
+PPDU-TxS is also capable of getting tx_bytes and tx_retries,
+but we'll get that from mcu command and TxFree instead.
+---
+ mt76_connac3_mac.h | 22 +++++++++++++++++++++-
+ mt7996/init.c | 5 +++++
+ mt7996/mac.c | 45 +++++++++++++++++++++++++++------------------
+ mt7996/regs.h | 7 +++++++
+ 4 files changed, 60 insertions(+), 19 deletions(-)
+
+diff --git a/mt76_connac3_mac.h b/mt76_connac3_mac.h
+index 20a2fe9..7402de2 100644
+--- a/mt76_connac3_mac.h
++++ b/mt76_connac3_mac.h
+@@ -281,6 +281,12 @@ enum tx_mgnt_type {
+ #define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
+ #define MT_TXFREE_INFO_STAT GENMASK(29, 28)
+
++enum {
++ MT_TXS_MPDU_FM0,
++ MT_TXS_MPDU_FM1,
++ MT_TXS_PPDU_FM
++};
++
+ #define MT_TXS0_BW GENMASK(31, 29)
+ #define MT_TXS0_TID GENMASK(28, 26)
+ #define MT_TXS0_AMPDU BIT(25)
+@@ -306,7 +312,7 @@ enum tx_mgnt_type {
+
+ #define MT_TXS2_BF_STATUS GENMASK(31, 30)
+ #define MT_TXS2_BAND GENMASK(29, 28)
+-#define MT_TXS2_WCID GENMASK(27, 16)
++#define MT_TXS2_MLD_ID GENMASK(27, 16)
+ #define MT_TXS2_TX_DELAY GENMASK(15, 0)
+
+ #define MT_TXS3_PID GENMASK(31, 24)
+@@ -318,6 +324,7 @@ enum tx_mgnt_type {
+
+ #define MT_TXS4_TIMESTAMP GENMASK(31, 0)
+
++/* MPDU based TXS */
+ #define MT_TXS5_F0_FINAL_MPDU BIT(31)
+ #define MT_TXS5_F0_QOS BIT(30)
+ #define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
+@@ -339,4 +346,17 @@ enum tx_mgnt_type {
+ #define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
+ #define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
+
++/* PPDU based TXS */
++#define MT_TXS5_MPDU_TX_CNT GENMASK(30, 20)
++#define MT_TXS5_MPDU_TX_BYTE_SCALE BIT(15)
++#define MT_TXS5_MPDU_TX_BYTE GENMASK(14, 0)
++
++#define MT_TXS6_MPDU_FAIL_CNT GENMASK(30, 20)
++#define MT_TXS6_MPDU_FAIL_BYTE_SCALE BIT(15)
++#define MT_TXS6_MPDU_FAIL_BYTE GENMASK(14, 0)
++
++#define MT_TXS7_MPDU_RETRY_CNT GENMASK(30, 20)
++#define MT_TXS7_MPDU_RETRY_BYTE_SCALE BIT(15)
++#define MT_TXS7_MPDU_RETRY_BYTE GENMASK(14, 0)
++
+ #endif /* __MT76_CONNAC3_MAC_H */
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 17a4abd..3656b89 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -456,6 +456,11 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
+ set = FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_MODE, 0) |
+ FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_PARAM, 0x3);
+ mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
++
++ /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
++ * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
++ */
++ mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
+ }
+
+ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 4828f10..7512147 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1227,22 +1227,35 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
+ bool cck = false;
+ u32 txrate, txs, mode, stbc;
+
++ txs = le32_to_cpu(txs_data[0]);
++
+ mt76_tx_status_lock(mdev, &list);
+ skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+- if (!skb)
+- goto out_no_skb;
+
+- txs = le32_to_cpu(txs_data[0]);
++ if (skb) {
++ info = IEEE80211_SKB_CB(skb);
++ if (!(txs & MT_TXS0_ACK_ERROR_MASK))
++ info->flags |= IEEE80211_TX_STAT_ACK;
+
+- info = IEEE80211_SKB_CB(skb);
+- if (!(txs & MT_TXS0_ACK_ERROR_MASK))
+- info->flags |= IEEE80211_TX_STAT_ACK;
++ info->status.ampdu_len = 1;
++ info->status.ampdu_ack_len = !!(info->flags &
++ IEEE80211_TX_STAT_ACK);
++
++ info->status.rates[0].idx = -1;
++ }
+
+- info->status.ampdu_len = 1;
+- info->status.ampdu_ack_len = !!(info->flags &
+- IEEE80211_TX_STAT_ACK);
++ /* PPDU based reporting */
++ if (FIELD_GET(MT_TXS0_TXS_FORMAT,txs) == MT_TXS_PPDU_FM) {
++ if (wcid->sta) {
++ struct ieee80211_sta *sta;
++ u8 tid;
+
+- info->status.rates[0].idx = -1;
++ sta = container_of((void *)wcid, struct ieee80211_sta,
++ drv_priv);
++ tid = FIELD_GET(MT_TXS0_TID, txs);
++ ieee80211_refresh_tx_agg_session_timer(sta, tid);
++ }
++ }
+
+ txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
+
+@@ -1342,9 +1355,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
+ wcid->rate = rate;
+
+ out:
+- mt76_tx_status_skb_done(mdev, skb, &list);
+-
+-out_no_skb:
++ if (skb)
++ mt76_tx_status_skb_done(mdev, skb, &list);
+ mt76_tx_status_unlock(mdev, &list);
+
+ return !!skb;
+@@ -1358,13 +1370,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
+ u16 wcidx;
+ u8 pid;
+
+- if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
+- return;
+-
+- wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
++ wcidx = le32_get_bits(txs_data[2], MT_TXS2_MLD_ID);
+ pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
+
+- if (pid < MT_PACKET_ID_FIRST)
++ if (pid < MT_PACKET_ID_WED)
+ return;
+
+ if (wcidx >= mt7996_wtbl_size(dev))
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index bd0eb51..865e005 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -275,6 +275,13 @@ enum base_rev {
+ FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
+ FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
+
++/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */
++#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band))
++#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
++
++#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, 0x3c)
++#define MT_AGG_ACR_PPDU_TXS2H BIT(1)
++
+ /* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */
+ #define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band))
+ #define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
deleted file mode 100644
index 1fef46a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 2fe477b8db9ab494a975a565a28e35fff76505d1 Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Thu, 16 Mar 2023 16:09:51 +0800
-Subject: [PATCH 19/39] wifi: mt76: mt7996: fix beamform mcu cmd configuration
-
-bf_num means how many band can support beamform, so the value shall be 3.
-bf_bitmap represents which band can support beamform.
----
- mt7996/mcu.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 349c20e..62e4869 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -3444,8 +3444,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
-
- tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en));
- req_mod_en = (struct bf_mod_en_ctrl *)tlv;
-- req_mod_en->bf_num = 2;
-- req_mod_en->bf_bitmap = GENMASK(0, 0);
-+ req_mod_en->bf_num = 3;
-+ req_mod_en->bf_bitmap = GENMASK(2, 0);
- break;
- }
- default:
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch
new file mode 100644
index 0000000..5cee6a0
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch
@@ -0,0 +1,233 @@
+From e66867f6acc33faa75e9e301ad64e0903cffd7be Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Fri, 14 Jul 2023 09:43:53 +0800
+Subject: [PATCH 20/98] wifi: mt76: mt7996: fix incorrect report of TX GI
+
+---
+ mt76_connac_mcu.h | 2 +-
+ mt7996/mac.c | 48 +++--------------------------------------------
+ mt7996/main.c | 1 +
+ mt7996/mcu.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h | 22 ++++++++++++++++++++++
+ 5 files changed, 74 insertions(+), 46 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index e9dd9aa..8562ca4 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1327,7 +1327,7 @@ enum {
+ };
+
+ enum UNI_ALL_STA_INFO_TAG {
+- UNI_ALL_STA_TX_RATE,
++ UNI_ALL_STA_TXRX_RATE,
+ UNI_ALL_STA_TX_STAT,
+ UNI_ALL_STA_TXRX_ADM_STAT,
+ UNI_ALL_STA_TXRX_AIR_TIME,
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 7512147..06c9a14 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -102,7 +102,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ };
+ struct ieee80211_sta *sta;
+ struct mt7996_sta *msta;
+- struct rate_info *rate;
+ u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
+ LIST_HEAD(sta_poll_list);
+ int i;
+@@ -118,7 +117,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ u32 addr, val;
+ u16 idx;
+ s8 rssi[4];
+- u8 bw;
+
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ if (list_empty(&sta_poll_list)) {
+@@ -174,49 +172,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
+ }
+
+- /* We don't support reading GI info from txs packets.
+- * For accurate tx status reporting and AQL improvement,
+- * we need to make sure that flags match so polling GI
+- * from per-sta counters directly.
+- */
+- rate = &msta->wcid.rate;
+-
+- switch (rate->bw) {
+- case RATE_INFO_BW_320:
+- bw = IEEE80211_STA_RX_BW_320;
+- break;
+- case RATE_INFO_BW_160:
+- bw = IEEE80211_STA_RX_BW_160;
+- break;
+- case RATE_INFO_BW_80:
+- bw = IEEE80211_STA_RX_BW_80;
+- break;
+- case RATE_INFO_BW_40:
+- bw = IEEE80211_STA_RX_BW_40;
+- break;
+- default:
+- bw = IEEE80211_STA_RX_BW_20;
+- break;
+- }
+-
+- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6);
+- val = mt76_rr(dev, addr);
+- if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) {
+- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5);
+- val = mt76_rr(dev, addr);
+- rate->eht_gi = FIELD_GET(GENMASK(25, 24), val);
+- } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) {
+- u8 offs = 24 + 2 * bw;
+-
+- rate->he_gi = (val & (0x3 << offs)) >> offs;
+- } else if (rate->flags &
+- (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) {
+- if (val & BIT(12 + bw))
+- rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
+- else
+- rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
+- }
+-
+ /* get signal strength of resp frames (CTS/BA/ACK) */
+ addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
+ val = mt76_rr(dev, addr);
+@@ -1303,6 +1258,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
+ goto out;
+
+ rate.flags = RATE_INFO_FLAGS_VHT_MCS;
++ if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
++ rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case MT_PHY_TYPE_HE_SU:
+ case MT_PHY_TYPE_HE_EXT_SU:
+@@ -2282,6 +2239,7 @@ void mt7996_mac_work(struct work_struct *work)
+
+ mt7996_mac_update_stats(phy);
+
++ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_RATE);
+ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
+ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
+ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index e9e1fd9..0b3f8c8 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -991,6 +991,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
+ sinfo->txrate.he_gi = txrate->he_gi;
+ sinfo->txrate.he_dcm = txrate->he_dcm;
+ sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
++ sinfo->txrate.eht_gi = txrate->eht_gi;
+ }
+ sinfo->txrate.flags = txrate->flags;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 652a600..c190067 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -477,6 +477,43 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
+ phy->throttle_state = n->duty_percent;
+ }
+
++static int
++mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate)
++{
++ switch (mcu_rate->tx_mode) {
++ case MT_PHY_TYPE_CCK:
++ case MT_PHY_TYPE_OFDM:
++ break;
++ case MT_PHY_TYPE_HT:
++ case MT_PHY_TYPE_HT_GF:
++ case MT_PHY_TYPE_VHT:
++ if (mcu_rate->tx_gi)
++ rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
++ else
++ rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
++ break;
++ case MT_PHY_TYPE_HE_SU:
++ case MT_PHY_TYPE_HE_EXT_SU:
++ case MT_PHY_TYPE_HE_TB:
++ case MT_PHY_TYPE_HE_MU:
++ if (mcu_rate->tx_gi > NL80211_RATE_INFO_HE_GI_3_2)
++ return -EINVAL;
++ rate->he_gi = mcu_rate->tx_gi;
++ break;
++ case MT_PHY_TYPE_EHT_SU:
++ case MT_PHY_TYPE_EHT_TRIG:
++ case MT_PHY_TYPE_EHT_MU:
++ if (mcu_rate->tx_gi > NL80211_RATE_INFO_EHT_GI_3_2)
++ return -EINVAL;
++ rate->eht_gi = mcu_rate->tx_gi;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static void
+ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -493,6 +530,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ struct mt76_wcid *wcid;
+
+ switch (le16_to_cpu(res->tag)) {
++ case UNI_ALL_STA_TXRX_RATE:
++ wlan_idx = le16_to_cpu(res->rate[i].wlan_idx);
++ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
++
++ if (!wcid)
++ break;
++
++ if (mt7996_mcu_update_tx_gi(&wcid->rate, &res->rate[i]))
++ dev_err(dev->mt76.dev, "Failed to update TX GI\n");
++ break;
+ case UNI_ALL_STA_TXRX_ADM_STAT:
+ wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 97151d1..376931e 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -191,6 +191,27 @@ struct mt7996_mcu_thermal_notify {
+ u8 __rsv2[4];
+ } __packed;
+
++struct all_sta_trx_rate {
++ __le16 wlan_idx;
++ u8 __rsv1[2];
++ u8 tx_mode;
++ u8 flags;
++ u8 tx_stbc;
++ u8 tx_gi;
++ u8 tx_bw;
++ u8 tx_ldpc;
++ u8 tx_mcs;
++ u8 tx_nss;
++ u8 rx_rate;
++ u8 rx_mode;
++ u8 rx_nsts;
++ u8 rx_gi;
++ u8 rx_coding;
++ u8 rx_stbc;
++ u8 rx_bw;
++ u8 __rsv2;
++} __packed;
++
+ struct mt7996_mcu_all_sta_info_event {
+ u8 rsv[4];
+ __le16 tag;
+@@ -201,6 +222,7 @@ struct mt7996_mcu_all_sta_info_event {
+ u8 rsv3[2];
+
+ union {
++ struct all_sta_trx_rate rate[0];
+ struct {
+ __le16 wlan_idx;
+ u8 rsv[2];
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
deleted file mode 100644
index 14855c7..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
+++ /dev/null
@@ -1,183 +0,0 @@
-From bfb2498bbef4bcfd44658fad8acf82730c56ede6 Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Tue, 20 Dec 2022 09:47:31 +0800
-Subject: [PATCH] wifi: mt76: mt7996: support more options in
- .set_bitrate_mask()
-
-With this patch, driver can support runtime configuration for single
-rate, (HE)GI and HE_Ltf through .set_bitrate_mask(). Please noted that
-currently we do not support to fix any single parameter for EHT mode.
-
-Co-developed-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
-Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
-Co-developed-by: Howard Hsu <howard-yh.hsu@mediatek.com>
-Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
----
- mt7996/mcu.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 135 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 62e4869..b7f378a 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -1656,6 +1656,134 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
- MCU_WM_UNI_CMD(RA), true);
- }
-
-+static int
-+mt7996_mcu_set_part_fixed_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta, void *data, u32 field)
-+{
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-+ struct sta_phy *phy = data;
-+ struct sta_rec_ra_fixed *ra;
-+ struct sk_buff *skb;
-+ struct tlv *tlv;
-+
-+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
-+ &msta->wcid,
-+ MT7996_STA_UPDATE_MAX_SIZE);
-+
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
-+ ra = (struct sta_rec_ra_fixed*)tlv;
-+
-+ switch (field) {
-+ case RATE_PARAM_AUTO:
-+ break;
-+ case RATE_PARAM_FIXED:
-+ case RATE_PARAM_FIXED_MCS:
-+ case RATE_PARAM_FIXED_GI:
-+ case RATE_PARAM_FIXED_HE_LTF:
-+ if (phy)
-+ ra->phy = *phy;
-+ break;
-+ default:
-+ break;
-+ }
-+ ra->field = cpu_to_le32(field);
-+
-+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
-+}
-+
-+
-+static int
-+mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
-+ struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
-+ enum nl80211_band band = chandef->chan->band;
-+ struct sta_phy phy = {};
-+ int ret, nrates = 0;
-+
-+#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
-+ do { \
-+ u8 i, gi = mask->control[band]._gi; \
-+ gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
-+ phy.sgi = gi; \
-+ phy.he_ltf = mask->control[band].he_ltf; \
-+ for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
-+ if (!mask->control[band]._mcs[i]) \
-+ continue; \
-+ nrates += hweight16(mask->control[band]._mcs[i]); \
-+ phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
-+ if (_ht) \
-+ phy.mcs += 8 * i; \
-+ } \
-+ } while (0)
-+
-+ if (sta->deflink.he_cap.has_he) {
-+ __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
-+ } else if (sta->deflink.vht_cap.vht_supported) {
-+ __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
-+ } else if (sta->deflink.ht_cap.ht_supported) {
-+ __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
-+ } else {
-+ nrates = hweight32(mask->control[band].legacy);
-+ phy.mcs = ffs(mask->control[band].legacy) - 1;
-+ }
-+#undef __sta_phy_bitrate_mask_check
-+
-+ /* fall back to auto rate control */
-+ if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
-+ mask->control[band].he_gi == GENMASK(7, 0) &&
-+ mask->control[band].he_ltf == GENMASK(7, 0) &&
-+ nrates != 1)
-+ return 0;
-+
-+ /* fixed single rate */
-+ if (nrates == 1) {
-+ ret = mt7996_mcu_set_part_fixed_rate_ctrl(dev, vif, sta, &phy,
-+ RATE_PARAM_FIXED_MCS);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ /* fixed GI */
-+ if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
-+ mask->control[band].he_gi != GENMASK(7, 0)) {
-+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-+ u32 addr;
-+
-+ /* firmware updates only TXCMD but doesn't take WTBL into
-+ * account, so driver should update here to reflect the
-+ * actual txrate hardware sends out.
-+ */
-+ addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
-+ if (sta->deflink.he_cap.has_he)
-+ mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
-+ else
-+ mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
-+
-+ ret = mt7996_mcu_set_part_fixed_rate_ctrl(dev, vif, sta, &phy,
-+ RATE_PARAM_FIXED_GI);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ /* fixed HE_LTF */
-+ if (mask->control[band].he_ltf != GENMASK(7, 0)) {
-+ ret = mt7996_mcu_set_part_fixed_rate_ctrl(dev, vif, sta, &phy,
-+ RATE_PARAM_FIXED_HE_LTF);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
- static void
- mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta)
-@@ -1765,6 +1893,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
- struct sk_buff *skb;
-+ int ret;
-
- skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
- &msta->wcid,
-@@ -1784,8 +1913,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- */
- mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
-
-- return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-- MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
-+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
-+ if (ret)
-+ return ret;
-+
-+ return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
- }
-
- static int
---
-2.39.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch
new file mode 100644
index 0000000..a5a8417
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch
@@ -0,0 +1,119 @@
+From e6830d67bbbc38036cd077badd5a605b8f257752 Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Thu, 27 Jul 2023 14:00:30 +0800
+Subject: [PATCH 21/98] wifi: mt76: mt7996: remove periodic MPDU TXS request
+
+---
+ mt7996/mac.c | 39 ++++++++++++++++++++++-----------------
+ mt7996/main.c | 1 -
+ mt7996/mt7996.h | 1 -
+ 3 files changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 06c9a14..32c52fc 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -926,15 +926,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ if (!wcid)
+ wcid = &dev->mt76.global_wcid;
+
+- if (sta) {
+- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+-
+- if (time_after(jiffies, msta->jiffies + HZ / 4)) {
+- info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+- msta->jiffies = jiffies;
+- }
+- }
+-
+ t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
+ t->skb = tx_info->skb;
+
+@@ -1010,22 +1001,36 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+ }
+
+ static void
+-mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
++mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
+ {
+ struct mt7996_sta *msta;
++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
+ u16 fc, tid;
+- u32 val;
+
+ if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
+ return;
+
+- tid = le32_get_bits(txwi[1], MT_TXD1_TID);
++ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+ if (tid >= 6) /* skip VO queue */
+ return;
+
+- val = le32_to_cpu(txwi[2]);
+- fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
+- FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
++ if (is_8023)
++ fc = IEEE80211_FTYPE_DATA |
++ (sta->wme ? IEEE80211_STYPE_QOS_DATA
++ : IEEE80211_STYPE_DATA);
++ else {
++ /* No need to get precise TID for Action/Management Frame,
++ * since it will not meet the following Frame Control
++ * condition anyway.
++ */
++
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++
++ fc = le16_to_cpu(hdr->frame_control) &
++ (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
++ }
++
+ if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
+ return;
+
+@@ -1053,7 +1058,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
+ wcid_idx = wcid->idx;
+
+ if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
+- mt7996_tx_check_aggr(sta, txwi);
++ mt7996_tx_check_aggr(sta, t->skb);
+ } else {
+ wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
+ }
+@@ -1330,7 +1335,7 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
+ wcidx = le32_get_bits(txs_data[2], MT_TXS2_MLD_ID);
+ pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
+
+- if (pid < MT_PACKET_ID_WED)
++ if (pid < MT_PACKET_ID_NO_SKB)
+ return;
+
+ if (wcidx >= mt7996_wtbl_size(dev))
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 0b3f8c8..832b861 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -666,7 +666,6 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ msta->wcid.idx = idx;
+ msta->wcid.phy_idx = band_idx;
+ msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+- msta->jiffies = jiffies;
+
+ ewma_avg_signal_init(&msta->avg_ack_signal);
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 420d113..f268773 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -147,7 +147,6 @@ struct mt7996_sta {
+ struct ewma_avg_signal avg_ack_signal;
+
+ unsigned long changed;
+- unsigned long jiffies;
+
+ struct mt76_connac_sta_key_conf bip;
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
deleted file mode 100644
index 6b1d684..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 88577bcf928a15c2e8e78b7684ccb75dfc693eac Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 20 Mar 2023 19:09:59 +0800
-Subject: [PATCH 21/39] wifi: mt76: mt7996: update wmm queue mapping
-
-The mac80211 use mac80211 queue (MQ) and the firmware
-use access class index (ACI) so convert the MQ to ACI
-in mt7996_conf_tx.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt7996/main.c | 11 +++++++++--
- mt7996/mcu.c | 2 +-
- 2 files changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 9c80839..8e38ebc 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -198,7 +198,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
- mvif->mt76.omac_idx = idx;
- mvif->phy = phy;
- mvif->mt76.band_idx = band_idx;
-- mvif->mt76.wmm_idx = band_idx;
-+ mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
-
- ret = mt7996_mcu_add_dev_info(phy, vif, true);
- if (ret)
-@@ -422,9 +422,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- const struct ieee80211_tx_queue_params *params)
- {
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ const u8 MQ_to_ACI[IEEE80211_NUM_ACS] = {
-+ [IEEE80211_AC_VO] = 3,
-+ [IEEE80211_AC_VI] = 2,
-+ [IEEE80211_AC_BE] = 0,
-+ [IEEE80211_AC_BK] = 1,
-+ };
-
- /* no need to update right away, we'll get BSS_CHANGED_QOS */
-- queue = mt76_connac_lmac_mapping(queue);
-+ /* convert mac80211 queue to ACI */
-+ queue = MQ_to_ACI[queue];
- mvif->queue_params[queue] = *params;
-
- return 0;
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index b27b88c..4359ede 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2835,7 +2835,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
-
- e = (struct edca *)tlv;
- e->set = WMM_PARAM_SET;
-- e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS;
-+ e->queue = ac;
- e->aifs = q->aifs;
- e->txop = cpu_to_le16(q->txop);
-
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch
new file mode 100644
index 0000000..575b7db
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch
@@ -0,0 +1,55 @@
+From 1b0bafc1cfb554b6150eb2ea3e1a5100ef1b0a24 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 24 Aug 2023 18:38:11 +0800
+Subject: [PATCH 22/98] wifi: mt76: connac: use peer address for station BMC
+ entry
+
+Set peer address and aid for the BMC wtbl of station interface. For some
+functions such as parsing MU_EDCA parameters from beacon, firmware will
+need peer address to do the correct mapping.
+
+Change-Id: I0e812312fe730f69f8e431215b8e591c5faec06a
+Reported-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt76_connac_mcu.c | 9 ++++++++-
+ mt7996/main.c | 3 +++
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index 68de525..bb570f2 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -391,7 +391,14 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
+
+ if (!sta) {
+ basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);
+- eth_broadcast_addr(basic->peer_addr);
++
++ if (vif->type == NL80211_IFTYPE_STATION &&
++ !is_zero_ether_addr(vif->bss_conf.bssid)) {
++ memcpy(basic->peer_addr, vif->bss_conf.bssid, ETH_ALEN);
++ basic->aid = cpu_to_le16(vif->cfg.aid);
++ } else {
++ eth_broadcast_addr(basic->peer_addr);
++ }
+ return;
+ }
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 832b861..0e51fe0 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -582,6 +582,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
+ (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
+ (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
++ /* reset bmc wtbl once BSSID changed */
++ if (changed & BSS_CHANGED_BSSID)
++ mt7996_mcu_add_sta(dev, vif, NULL, false);
+ mt7996_mcu_add_bss_info(phy, vif, true);
+ mt7996_mcu_add_sta(dev, vif, NULL, true);
+ }
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch
deleted file mode 100644
index 659edd4..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 7e3ab3b90fc75ff41a503f4632a669c8cba2ae90 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Tue, 21 Mar 2023 15:04:45 +0800
-Subject: [PATCH 22/39] wifi: mt76: mt7996: enable IDS debug log
-
----
- mt7996/debugfs.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 513ab4b..0422018 100644
---- a/mt7996/debugfs.c
-+++ b/mt7996/debugfs.c
-@@ -290,6 +290,12 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
- DEBUG_SPL,
- DEBUG_RPT_RX,
- DEBUG_RPT_RA = 68,
-+ DEBUG_IDS_PP = 93,
-+ DEBUG_IDS_RA = 94,
-+ DEBUG_IDS_BF = 95,
-+ DEBUG_IDS_SR = 96,
-+ DEBUG_IDS_RU = 97,
-+ DEBUG_IDS_MUMIMO = 98,
- } debug;
- bool tx, rx, en;
- int ret;
-@@ -309,8 +315,8 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
- if (ret)
- return ret;
-
-- for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RA; debug++) {
-- if (debug == 67)
-+ for (debug = DEBUG_TXCMD; debug <= DEBUG_IDS_MUMIMO; debug++) {
-+ if (debug == 67 || (debug > DEBUG_RPT_RA && debug < DEBUG_IDS_PP))
- continue;
-
- if (debug == DEBUG_RPT_RX)
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch
new file mode 100644
index 0000000..1494376
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch
@@ -0,0 +1,51 @@
+From cb01c8f9cef451d5e478d8498902d52a92ca4b55 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 5 Sep 2023 17:31:49 +0800
+Subject: [PATCH 23/98] wifi: mt76: mt7996: disable rx header translation for
+ BMC entry
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: Ia98bb775af528fe1002590fa25bb8855945cfc4b
+---
+ mt7996/mcu.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index c190067..39f76a0 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1719,10 +1719,10 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+ else
+ hdr_trans->from_ds = true;
+
+- wcid = (struct mt76_wcid *)sta->drv_priv;
+- if (!wcid)
++ if (!sta)
+ return;
+
++ wcid = (struct mt76_wcid *)sta->drv_priv;
+ hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
+ if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
+ hdr_trans->to_ds = true;
+@@ -2095,6 +2095,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ if (!enable)
+ goto out;
+
++ /* starec hdr trans */
++ mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta);
++
+ /* tag order is in accordance with firmware dependency. */
+ if (sta) {
+ /* starec phy */
+@@ -2121,8 +2124,6 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta);
+ /* starec bfee */
+ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
+- /* starec hdr trans */
+- mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta);
+ }
+
+ ret = mt7996_mcu_add_group(dev, vif, sta);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-mt7996-add-kite-pci-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-mt7996-add-kite-pci-support.patch
new file mode 100644
index 0000000..d3c12af
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-mt7996-add-kite-pci-support.patch
@@ -0,0 +1,81 @@
+From 140d3c7139e37efcdc097b1b23be635da683e773 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 22 May 2023 09:30:28 +0800
+Subject: [PATCH 24/98] wifi: mt76: mt7996: add kite pci support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac.h | 5 +++++
+ mt7996/mmio.c | 1 +
+ mt7996/pci.c | 8 ++++++--
+ 3 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/mt76_connac.h b/mt76_connac.h
+index c6726ab..b1ec8d4 100644
+--- a/mt76_connac.h
++++ b/mt76_connac.h
+@@ -222,6 +222,11 @@ static inline bool is_mt7996(struct mt76_dev *dev)
+ return mt76_chip(dev) == 0x7990;
+ }
+
++static inline bool is_mt7992(struct mt76_dev *dev)
++{
++ return mt76_chip(dev) == 0x7992;
++}
++
+ static inline bool is_mt7622(struct mt76_dev *dev)
+ {
+ if (!IS_ENABLED(CONFIG_MT7622_WMAC))
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index ab088a2..567f930 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -369,6 +369,7 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
+
+ switch (device_id) {
+ case 0x7990:
++ case 0x7992:
+ dev->reg.base = mt7996_reg_base;
+ dev->reg.map = mt7996_reg_map;
+ dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 92869ca..e8edf77 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -17,11 +17,13 @@ static u32 hif_idx;
+
+ static const struct pci_device_id mt7996_pci_device_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) },
++ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) },
+ { },
+ };
+
+ static const struct pci_device_id mt7996_hif_device_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) },
++ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) },
+ { },
+ };
+
+@@ -60,7 +62,9 @@ static void mt7996_put_hif2(struct mt7996_hif *hif)
+ static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
+ {
+ hif_idx++;
+- if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL))
++
++ if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&
++ !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))
+ return NULL;
+
+ writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
+@@ -113,7 +117,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+
+ mt76_pci_disable_aspm(pdev);
+
+- if (id->device == 0x7991)
++ if (id->device == 0x7991 || id->device == 0x799a)
+ return mt7996_pci_hif2_probe(pdev);
+
+ dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch
new file mode 100644
index 0000000..7ce6401
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch
@@ -0,0 +1,56 @@
+From 12f123f46ccce46990ce98d05a3a9db3b20b5459 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 14 Jun 2023 17:47:11 +0800
+Subject: [PATCH 25/98] wifi: mt76: mt7996: add kite wtbl size support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 3 ++-
+ mt7996/mt7996.h | 6 ++++--
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 9db7e53..ca0e9d0 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -103,7 +103,8 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
+ dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
+ }
+
+- if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4)
++ if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4 ||
++ is_mt7992(&dev->mt76))
+ dev->wtbl_size_group = 2; /* set default */
+
+ return 0;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index f268773..6a31819 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -13,6 +13,7 @@
+
+ #define MT7996_MAX_INTERFACES 19 /* per-band */
+ #define MT7996_MAX_WMM_SETS 4
++#define MT7996_WTBL_EXTEND_SIZE (is_mt7992(&dev->mt76) ? 32 : 64)
+ #define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
+ #define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
+ mt7996_max_interface_num(dev))
+@@ -497,12 +498,13 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+- return MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support);
++ return min(MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support),
++ MT7996_WTBL_EXTEND_SIZE);
+ }
+
+ static inline u16 mt7996_wtbl_size(struct mt7996_dev *dev)
+ {
+- return (dev->wtbl_size_group << 8) + 64;
++ return (dev->wtbl_size_group << 8) + MT7996_WTBL_EXTEND_SIZE;
+ }
+
+ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch
new file mode 100644
index 0000000..d494783
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch
@@ -0,0 +1,28 @@
+From f364ba42a956ba321876c2ac3798811cd8ea88f3 Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Wed, 7 Jun 2023 10:21:09 +0800
+Subject: [PATCH 26/98] wifi: mt76: mt7996: accommodate MT7992 with different
+ capability
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt7996/mt7996.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 6a31819..31fa2b5 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -390,6 +390,9 @@ mt7996_phy3(struct mt7996_dev *dev)
+ static inline bool
+ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
+ {
++ if (is_mt7992(&dev->mt76))
++ return band <= MT_BAND1;
++
+ /* tri-band support */
+ if (band <= MT_BAND2 &&
+ mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch
deleted file mode 100644
index 06e273a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From 030159528eff349db01b6b47b6fff8112b4282a4 Mon Sep 17 00:00:00 2001
-From: mtk25577 <jen-hao.cheng@mediatek.com>
-Date: Tue, 28 Mar 2023 18:23:00 +0800
-Subject: [PATCH 26/39] wifi: mt76: mt7996: add led feature support
-
-Signed-off-by: mtk25577 <jen-hao.cheng@mediatek.com>
----
- mt7996/Makefile | 1 +
- mt7996/init.c | 33 +++++++++++++++++++++------------
- mt7996/regs.h | 1 +
- 3 files changed, 23 insertions(+), 12 deletions(-)
-
-diff --git a/mt7996/Makefile b/mt7996/Makefile
-index bed9efd..7c2514a 100644
---- a/mt7996/Makefile
-+++ b/mt7996/Makefile
-@@ -1,4 +1,5 @@
- # SPDX-License-Identifier: ISC
-+EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
-
- obj-$(CONFIG_MT7996E) += mt7996e.o
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index fecd0d3..192af3f 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -232,23 +232,31 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev,
- dev = container_of(mphy->dev, struct mt7996_dev, mt76);
-
- /* select TX blink mode, 2: only data frames */
-- mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2);
-+ mt76_rmw_field(dev, MT_TMAC_TCR0(mphy->band_idx), MT_TMAC_TCR0_TX_BLINK, 2);
-
- /* enable LED */
-- mt76_wr(dev, MT_LED_EN(0), 1);
-+ mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);
-
- /* set LED Tx blink on/off time */
- val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) |
- FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off);
-- mt76_wr(dev, MT_LED_TX_BLINK(0), val);
-+ mt76_wr(dev, MT_LED_TX_BLINK(mphy->band_idx), val);
-+
-+ /* turn LED off */
-+ if (delay_off == 0xff && delay_on == 0x0)
-+ val = MT_LED_CTRL_POLARITY | MT_LED_CTRL_KICK;
-+ else {
-+ /* control LED */
-+ val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
-+ if (mphy->band_idx == MT_BAND1)
-+ val |= MT_LED_CTRL_BLINK_BAND_SEL;
-+ }
-
-- /* control LED */
-- val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
- if (mphy->leds.al)
- val |= MT_LED_CTRL_POLARITY;
-
-- mt76_wr(dev, MT_LED_CTRL(0), val);
-- mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK);
-+ mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);
-+ mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);
- }
-
- static int mt7996_led_set_blink(struct led_classdev *led_cdev,
-@@ -400,6 +408,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
- ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
- }
-
-+ /* init led callbacks */
-+ if (IS_ENABLED(CONFIG_MT76_LEDS)) {
-+ phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness;
-+ phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink;
-+ }
-+
- mt76_set_stream_caps(phy->mt76, true);
- mt7996_set_stream_vht_txbf_caps(phy);
- mt7996_set_stream_he_eht_caps(phy);
-@@ -1063,11 +1077,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
- #ifdef CONFIG_NL80211_TESTMODE
- dev->mt76.test_ops = &mt7996_testmode_ops;
- #endif
-- /* init led callbacks */
-- if (IS_ENABLED(CONFIG_MT76_LEDS)) {
-- dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
-- dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink;
-- }
-
- ret = mt76_register_device(&dev->mt76, true, mt76_rates,
- ARRAY_SIZE(mt76_rates));
-diff --git a/mt7996/regs.h b/mt7996/regs.h
-index d1d3d15..86da1bf 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -509,6 +509,7 @@ enum base_rev {
-
- #define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4))
- #define MT_LED_CTRL_KICK BIT(7)
-+#define MT_LED_CTRL_BLINK_BAND_SEL BIT(4)
- #define MT_LED_CTRL_BLINK_MODE BIT(2)
- #define MT_LED_CTRL_POLARITY BIT(1)
-
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch
new file mode 100644
index 0000000..3f5cfe7
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch
@@ -0,0 +1,47 @@
+From 41ae938fe5d3df6b40e2b1cd5baaf8ea59bd2c46 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 12 Jul 2023 23:00:29 +0800
+Subject: [PATCH 27/98] wifi: mt76: mt7996: add AFE pll enable before driver
+ own
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt7996/init.c | 4 ++++
+ mt7996/regs.h | 7 +++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 3656b89..273d1e7 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -782,6 +782,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ int ret, idx;
+
+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
++ if (is_mt7992(&dev->mt76)) {
++ mt76_rmw(dev, MT_AFE_CTL_BAND_PLL_03(MT_BAND0), MT_AFE_CTL_BAND_PLL_03_MSB_EN, 0);
++ mt76_rmw(dev, MT_AFE_CTL_BAND_PLL_03(MT_BAND1), MT_AFE_CTL_BAND_PLL_03_MSB_EN, 0);
++ }
+
+ INIT_WORK(&dev->init_work, mt7996_init_work);
+
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 865e005..e76dae6 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -675,4 +675,11 @@ enum base_rev {
+ #define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS GENMASK(20, 16)
+ #define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204)
+
++/* CONN AFE CTL CON */
++#define MT_AFE_CTL_BASE 0x18043000
++#define MT_AFE_CTL_BAND(_band, ofs) (MT_AFE_CTL_BASE + \
++ ((_band) * 0x1000) + (ofs))
++#define MT_AFE_CTL_BAND_PLL_03(_band) MT_AFE_CTL_BAND(_band, 0x2c)
++#define MT_AFE_CTL_BAND_PLL_03_MSB_EN BIT(1)
++
+ #endif
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch
deleted file mode 100644
index 2e938b7..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From e503dbe84bc2b46907a792e11c196018b274647a Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Tue, 28 Mar 2023 20:20:57 +0800
-Subject: [PATCH 27/39] wifi: mt76: mt7996: fix twt mcu command
-
-Update unified command for twt.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt7915/mcu.h | 1 -
- mt7996/mcu.c | 7 +++++--
- 2 files changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index b9ea297..e7a5395 100644
---- a/mt7915/mcu.h
-+++ b/mt7915/mcu.h
-@@ -264,7 +264,6 @@ enum {
- MCU_TWT_AGRT_MODIFY,
- MCU_TWT_AGRT_DELETE,
- MCU_TWT_AGRT_TEARDOWN,
-- MCU_TWT_AGRT_GET_TSF,
- };
-
- enum {
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index a6d8235..6bcb33e 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -3823,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
- int cmd)
- {
- struct {
-- u8 _rsv[4];
-+ /* fixed field */
-+ u8 bss;
-+ u8 _rsv[3];
-
- __le16 tag;
- __le16 len;
-@@ -3841,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
- u8 exponent;
- u8 is_ap;
- u8 agrt_params;
-- u8 __rsv2[135];
-+ u8 __rsv2[23];
- } __packed req = {
- .tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE),
- .len = cpu_to_le16(sizeof(req) - 4),
-@@ -3851,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
- .flowid = flow->id,
- .peer_id = cpu_to_le16(flow->wcid),
- .duration = flow->duration,
-+ .bss = mvif->mt76.idx,
- .bss_idx = mvif->mt76.idx,
- .start_tsf = cpu_to_le64(flow->tsf),
- .mantissa = flow->mantissa,
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch
deleted file mode 100644
index bf724c8..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch
+++ /dev/null
@@ -1,181 +0,0 @@
-From 0449694e4e963d0b48354ae2c52016c34899fba6 Mon Sep 17 00:00:00 2001
-From: mtk20656 <chank.chen@mediatek.com>
-Date: Wed, 8 Mar 2023 14:18:29 +0800
-Subject: [PATCH 28/39] wifi: mt76: mt7996: add 11v mbss support for mt76
-
-Signed-off-by: mtk20656 <chank.chen@mediatek.com>
----
- mt76_connac_mcu.h | 10 ++++++
- mt7996/init.c | 2 ++
- mt7996/mcu.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++-
- 3 files changed, 90 insertions(+), 1 deletion(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 724a48a..97f874b 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -1281,6 +1281,7 @@ enum {
- UNI_BSS_INFO_RLM = 2,
- UNI_BSS_INFO_BSS_COLOR = 4,
- UNI_BSS_INFO_HE_BASIC = 5,
-+ UNI_BSS_INFO_11V_MBSSID = 6,
- UNI_BSS_INFO_BCN_CONTENT = 7,
- UNI_BSS_INFO_BCN_CSA = 8,
- UNI_BSS_INFO_BCN_BCC = 9,
-@@ -1551,6 +1552,15 @@ struct bss_info_uni_he {
- u8 rsv[2];
- } __packed;
-
-+struct bss_info_uni_mbssid {
-+ __le16 tag;
-+ __le16 len;
-+ u8 max_indicator;
-+ u8 mbss_idx;
-+ u8 tx_bss_omac_idx;
-+ u8 rsv[1];
-+} __packed;
-+
- struct mt76_connac_gtk_rekey_tlv {
- __le16 tag;
- __le16 len;
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 192af3f..0562439 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -359,6 +359,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
- wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
- wiphy->reg_notifier = mt7996_regd_notifier;
- wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
-+ wiphy->mbssid_max_interfaces = 16;
-
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
-@@ -381,6 +382,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
- ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
- ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
- ieee80211_hw_set(hw, WANT_MONITOR_VIF);
-+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
-
- hw->max_tx_fragments = 4;
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6bcb33e..a369a08 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -631,6 +631,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
- he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
- }
-
-+static void
-+mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
-+ struct mt7996_phy *phy)
-+{
-+ struct bss_info_uni_mbssid *mbssid;
-+ struct tlv *tlv;
-+
-+ tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid));
-+
-+ mbssid = (struct bss_info_uni_mbssid *)tlv;
-+
-+ mbssid->max_indicator = vif->bss_conf.bssid_indicator;
-+ mbssid->mbss_idx = vif->bss_conf.bssid_index;
-+ mbssid->tx_bss_omac_idx = 0;
-+
-+ return;
-+}
-+
- static void
- mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
- struct mt7996_phy *phy)
-@@ -895,6 +913,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
- if (vif->bss_conf.he_support)
- mt7996_mcu_bss_he_tlv(skb, vif, phy);
-
-+ if (vif->bss_conf.bssid_indicator)
-+ mt7996_mcu_bss_mbssid_tlv(skb, vif, phy);
-+
- /* this tag is necessary no matter if the vif is MLD */
- mt7996_mcu_bss_mld_tlv(skb, vif);
- }
-@@ -2162,6 +2183,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
- info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
- }
-
-+static void
-+mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
-+ struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn,
-+ struct ieee80211_mutable_offsets *offs)
-+{
-+ struct bss_bcn_mbss_tlv *mbss;
-+ const struct element *elem;
-+ struct tlv *tlv;
-+
-+ if (!vif->bss_conf.bssid_indicator)
-+ return;
-+
-+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss));
-+
-+ mbss = (struct bss_bcn_mbss_tlv *)tlv;
-+ mbss->offset[0] = cpu_to_le16(offs->tim_offset);
-+ mbss->bitmap = cpu_to_le32(1);
-+
-+ for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
-+ &skb->data[offs->mbssid_off],
-+ skb->len - offs->mbssid_off) {
-+ const struct element *sub_elem;
-+
-+ if (elem->datalen < 2)
-+ continue;
-+
-+ for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
-+ const struct ieee80211_bssid_index *idx;
-+ const u8 *idx_ie;
-+
-+ if (sub_elem->id || sub_elem->datalen < 4)
-+ continue; /* not a valid BSS profile */
-+
-+ /* Find WLAN_EID_MULTI_BSSID_IDX
-+ * in the merged nontransmitted profile
-+ */
-+ idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
-+ sub_elem->data,
-+ sub_elem->datalen);
-+ if (!idx_ie || idx_ie[1] < sizeof(*idx))
-+ continue;
-+
-+ idx = (void *)(idx_ie + 2);
-+ if (!idx->bssid_index || idx->bssid_index > 31)
-+ continue;
-+
-+ mbss->offset[idx->bssid_index] =
-+ cpu_to_le16(idx_ie - skb->data);
-+ mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
-+ }
-+ }
-+}
-+
- static void
- mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- struct sk_buff *rskb, struct sk_buff *skb,
-@@ -2202,6 +2276,9 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
- struct tlv *tlv;
- struct bss_bcn_content_tlv *bcn;
-
-+ if (vif->bss_conf.nontransmitted)
-+ return 0;
-+
- rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
- MT7996_BEACON_UPDATE_SIZE);
- if (IS_ERR(rskb))
-@@ -2229,7 +2306,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
- info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
-
- mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
-- /* TODO: subtag - 11v MBSSID */
-+ mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
- mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
- dev_kfree_skb(skb);
- out:
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch
new file mode 100644
index 0000000..9d0f02b
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch
@@ -0,0 +1,232 @@
+From df9f668cf78a4c8dbc505f5fc0fb27a14e94f4c1 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 14 Jul 2023 17:29:35 +0800
+Subject: [PATCH 28/98] wifi: mt76: mt7996: add kite & eagle CR offset revision
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mmio.c | 58 +++++++++++++++++++++++++++++++++++++++
+ mt7996/regs.h | 76 +++++++++++++++++++++++++++++++++++----------------
+ 2 files changed, 111 insertions(+), 23 deletions(-)
+
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 567f930..2132b2e 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -28,6 +28,58 @@ static const struct __base mt7996_reg_base[] = {
+ [WF_RATE_BASE] = { { 0x820ee000, 0x820fe000, 0x830ee000 } },
+ };
+
++static const u32 mt7996_offs[] = {
++ [MIB_RVSR0] = 0x720,
++ [MIB_RVSR1] = 0x724,
++ [MIB_BTSCR5] = 0x788,
++ [MIB_BTSCR6] = 0x798,
++ [MIB_RSCR1] = 0x7ac,
++ [MIB_RSCR27] = 0x954,
++ [MIB_RSCR28] = 0x958,
++ [MIB_RSCR29] = 0x95c,
++ [MIB_RSCR30] = 0x960,
++ [MIB_RSCR31] = 0x964,
++ [MIB_RSCR33] = 0x96c,
++ [MIB_RSCR35] = 0x974,
++ [MIB_RSCR36] = 0x978,
++ [MIB_BSCR0] = 0x9cc,
++ [MIB_BSCR1] = 0x9d0,
++ [MIB_BSCR2] = 0x9d4,
++ [MIB_BSCR3] = 0x9d8,
++ [MIB_BSCR4] = 0x9dc,
++ [MIB_BSCR5] = 0x9e0,
++ [MIB_BSCR6] = 0x9e4,
++ [MIB_BSCR7] = 0x9e8,
++ [MIB_BSCR17] = 0xa10,
++ [MIB_TRDR1] = 0xa28,
++};
++
++static const u32 mt7992_offs[] = {
++ [MIB_RVSR0] = 0x760,
++ [MIB_RVSR1] = 0x764,
++ [MIB_BTSCR5] = 0x7c8,
++ [MIB_BTSCR6] = 0x7d8,
++ [MIB_RSCR1] = 0x7f0,
++ [MIB_RSCR27] = 0x998,
++ [MIB_RSCR28] = 0x99c,
++ [MIB_RSCR29] = 0x9a0,
++ [MIB_RSCR30] = 0x9a4,
++ [MIB_RSCR31] = 0x9a8,
++ [MIB_RSCR33] = 0x9b0,
++ [MIB_RSCR35] = 0x9b8,
++ [MIB_RSCR36] = 0x9bc,
++ [MIB_BSCR0] = 0xac8,
++ [MIB_BSCR1] = 0xacc,
++ [MIB_BSCR2] = 0xad0,
++ [MIB_BSCR3] = 0xad4,
++ [MIB_BSCR4] = 0xad8,
++ [MIB_BSCR5] = 0xadc,
++ [MIB_BSCR6] = 0xae0,
++ [MIB_BSCR7] = 0xae4,
++ [MIB_BSCR17] = 0xb0c,
++ [MIB_TRDR1] = 0xb24,
++};
++
+ static const struct __map mt7996_reg_map[] = {
+ { 0x54000000, 0x02000, 0x1000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */
+ { 0x55000000, 0x03000, 0x1000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */
+@@ -369,8 +421,14 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
+
+ switch (device_id) {
+ case 0x7990:
++ dev->reg.base = mt7996_reg_base;
++ dev->reg.offs_rev = mt7996_offs;
++ dev->reg.map = mt7996_reg_map;
++ dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
++ break;
+ case 0x7992:
+ dev->reg.base = mt7996_reg_base;
++ dev->reg.offs_rev = mt7992_offs;
+ dev->reg.map = mt7996_reg_map;
+ dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
+ break;
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index e76dae6..de5df91 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -19,6 +19,7 @@ struct __base {
+ /* used to differentiate between generations */
+ struct mt7996_reg_desc {
+ const struct __base *base;
++ const u32 *offs_rev;
+ const struct __map *map;
+ u32 map_size;
+ };
+@@ -39,6 +40,35 @@ enum base_rev {
+
+ #define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
+
++enum offs_rev {
++ MIB_RVSR0,
++ MIB_RVSR1,
++ MIB_BTSCR5,
++ MIB_BTSCR6,
++ MIB_RSCR1,
++ MIB_RSCR27,
++ MIB_RSCR28,
++ MIB_RSCR29,
++ MIB_RSCR30,
++ MIB_RSCR31,
++ MIB_RSCR33,
++ MIB_RSCR35,
++ MIB_RSCR36,
++ MIB_BSCR0,
++ MIB_BSCR1,
++ MIB_BSCR2,
++ MIB_BSCR3,
++ MIB_BSCR4,
++ MIB_BSCR5,
++ MIB_BSCR6,
++ MIB_BSCR7,
++ MIB_BSCR17,
++ MIB_TRDR1,
++ __MT_OFFS_MAX,
++};
++
++#define __OFFS(id) (dev->reg.offs_rev[(id)])
++
+ /* RRO TOP */
+ #define MT_RRO_TOP_BASE 0xA000
+ #define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
+@@ -172,32 +202,32 @@ enum base_rev {
+ #define MT_WF_MIB_BASE(_band) __BASE(WF_MIB_BASE, (_band))
+ #define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
+
+-#define MT_MIB_BSCR0(_band) MT_WF_MIB(_band, 0x9cc)
+-#define MT_MIB_BSCR1(_band) MT_WF_MIB(_band, 0x9d0)
+-#define MT_MIB_BSCR2(_band) MT_WF_MIB(_band, 0x9d4)
+-#define MT_MIB_BSCR3(_band) MT_WF_MIB(_band, 0x9d8)
+-#define MT_MIB_BSCR4(_band) MT_WF_MIB(_band, 0x9dc)
+-#define MT_MIB_BSCR5(_band) MT_WF_MIB(_band, 0x9e0)
+-#define MT_MIB_BSCR6(_band) MT_WF_MIB(_band, 0x9e4)
+-#define MT_MIB_BSCR7(_band) MT_WF_MIB(_band, 0x9e8)
+-#define MT_MIB_BSCR17(_band) MT_WF_MIB(_band, 0xa10)
++#define MT_MIB_BSCR0(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR0))
++#define MT_MIB_BSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR1))
++#define MT_MIB_BSCR2(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR2))
++#define MT_MIB_BSCR3(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR3))
++#define MT_MIB_BSCR4(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR4))
++#define MT_MIB_BSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR5))
++#define MT_MIB_BSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR6))
++#define MT_MIB_BSCR7(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR7))
++#define MT_MIB_BSCR17(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR17))
+
+ #define MT_MIB_TSCR5(_band) MT_WF_MIB(_band, 0x6c4)
+ #define MT_MIB_TSCR6(_band) MT_WF_MIB(_band, 0x6c8)
+ #define MT_MIB_TSCR7(_band) MT_WF_MIB(_band, 0x6d0)
+
+-#define MT_MIB_RSCR1(_band) MT_WF_MIB(_band, 0x7ac)
++#define MT_MIB_RSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR1))
+ /* rx mpdu counter, full 32 bits */
+-#define MT_MIB_RSCR31(_band) MT_WF_MIB(_band, 0x964)
+-#define MT_MIB_RSCR33(_band) MT_WF_MIB(_band, 0x96c)
++#define MT_MIB_RSCR31(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR31))
++#define MT_MIB_RSCR33(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR33))
+
+ #define MT_MIB_SDR6(_band) MT_WF_MIB(_band, 0x020)
+ #define MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK GENMASK(15, 0)
+
+-#define MT_MIB_RVSR0(_band) MT_WF_MIB(_band, 0x720)
++#define MT_MIB_RVSR0(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR0))
+
+-#define MT_MIB_RSCR35(_band) MT_WF_MIB(_band, 0x974)
+-#define MT_MIB_RSCR36(_band) MT_WF_MIB(_band, 0x978)
++#define MT_MIB_RSCR35(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR35))
++#define MT_MIB_RSCR36(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR36))
+
+ /* tx ampdu cnt, full 32 bits */
+ #define MT_MIB_TSCR0(_band) MT_WF_MIB(_band, 0x6b0)
+@@ -210,16 +240,16 @@ enum base_rev {
+ #define MT_MIB_TSCR4(_band) MT_WF_MIB(_band, 0x6c0)
+
+ /* rx ampdu count, 32-bit */
+-#define MT_MIB_RSCR27(_band) MT_WF_MIB(_band, 0x954)
++#define MT_MIB_RSCR27(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR27))
+
+ /* rx ampdu bytes count, 32-bit */
+-#define MT_MIB_RSCR28(_band) MT_WF_MIB(_band, 0x958)
++#define MT_MIB_RSCR28(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR28))
+
+ /* rx ampdu valid subframe count */
+-#define MT_MIB_RSCR29(_band) MT_WF_MIB(_band, 0x95c)
++#define MT_MIB_RSCR29(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR29))
+
+ /* rx ampdu valid subframe bytes count, 32bits */
+-#define MT_MIB_RSCR30(_band) MT_WF_MIB(_band, 0x960)
++#define MT_MIB_RSCR30(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR30))
+
+ /* remaining windows protected stats */
+ #define MT_MIB_SDR27(_band) MT_WF_MIB(_band, 0x080)
+@@ -228,18 +258,18 @@ enum base_rev {
+ #define MT_MIB_SDR28(_band) MT_WF_MIB(_band, 0x084)
+ #define MT_MIB_SDR28_TX_RWP_NEED_CNT GENMASK(15, 0)
+
+-#define MT_MIB_RVSR1(_band) MT_WF_MIB(_band, 0x724)
++#define MT_MIB_RVSR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR1))
+
+ /* rx blockack count, 32 bits */
+ #define MT_MIB_TSCR1(_band) MT_WF_MIB(_band, 0x6b4)
+
+ #define MT_MIB_BTSCR0(_band) MT_WF_MIB(_band, 0x5e0)
+-#define MT_MIB_BTSCR5(_band) MT_WF_MIB(_band, 0x788)
+-#define MT_MIB_BTSCR6(_band) MT_WF_MIB(_band, 0x798)
++#define MT_MIB_BTSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR5))
++#define MT_MIB_BTSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR6))
+
+ #define MT_MIB_BFTFCR(_band) MT_WF_MIB(_band, 0x5d0)
+
+-#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0xa28 + ((n) << 2))
++#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, __OFFS(MIB_TRDR1) + ((n) << 2))
+ #define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2))
+ #define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 4)) & GENMASK(9, 0))
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch
deleted file mode 100644
index 67e5c6c..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch
+++ /dev/null
@@ -1,188 +0,0 @@
-From 8b591f425b1bb71ebde4a1eb9c926f0c9017fe28 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Mon, 27 Mar 2023 09:47:44 +0800
-Subject: [PATCH 29/39] wifi: mt76: mt7996: Update beacon size limitation for
- 11v
-
-The TLV size limitation for these two has been expanded to
-accommodate 11v MBSSID IE.
-
-Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
-Co-developed-by: Money Wang <Money.Wang@mediatek.com>
-Signed-off-by: Money Wang <Money.Wang@mediatek.com>
-Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
----
- mt7996/main.c | 4 ++--
- mt7996/mcu.c | 39 +++++++++++++++++++++++----------------
- mt7996/mcu.h | 11 ++++-------
- 3 files changed, 29 insertions(+), 25 deletions(-)
-
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 6c38993..520f250 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -618,8 +618,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
- mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
- }
-
-- if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
-- changed & BSS_CHANGED_FILS_DISCOVERY)
-+ if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
-+ BSS_CHANGED_FILS_DISCOVERY))
- mt7996_mcu_beacon_inband_discov(dev, vif, changed);
-
- mutex_unlock(&dev->mt76.mutex);
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index a369a08..7b8f883 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2257,7 +2257,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
- bcn->bcc_ie_pos = cpu_to_le16(offset - 3);
- }
-
-- buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
-+ buf = (u8 *)bcn + sizeof(*bcn);
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
- BSS_CHANGED_BEACON);
-
-@@ -2275,28 +2275,21 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
- struct sk_buff *skb, *rskb;
- struct tlv *tlv;
- struct bss_bcn_content_tlv *bcn;
-+ int len;
-
- if (vif->bss_conf.nontransmitted)
- return 0;
-
- rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
-- MT7996_BEACON_UPDATE_SIZE);
-+ MT7996_MAX_BSS_OFFLOAD_SIZE);
- if (IS_ERR(rskb))
- return PTR_ERR(rskb);
-
-- tlv = mt7996_mcu_add_uni_tlv(rskb,
-- UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn));
-- bcn = (struct bss_bcn_content_tlv *)tlv;
-- bcn->enable = en;
--
-- if (!en)
-- goto out;
--
- skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
- if (!skb)
- return -EINVAL;
-
-- if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
-+ if (skb->len > MT7996_MAX_BEACON_SIZE) {
- dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
- dev_kfree_skb(skb);
- return -EINVAL;
-@@ -2305,11 +2298,19 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
- info = IEEE80211_SKB_CB(skb);
- info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
-
-+ len = sizeof(*bcn) + MT_TXD_SIZE + skb->len;
-+ tlv = mt7996_mcu_add_uni_tlv(rskb,
-+ UNI_BSS_INFO_BCN_CONTENT, len);
-+ bcn = (struct bss_bcn_content_tlv *)tlv;
-+ bcn->enable = en;
-+ if (!en)
-+ goto out;
-+
- mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
- mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
- mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
-- dev_kfree_skb(skb);
- out:
-+ dev_kfree_skb(skb);
- return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
- MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
- }
-@@ -2330,9 +2331,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
- struct sk_buff *rskb, *skb = NULL;
- struct tlv *tlv;
- u8 *buf, interval;
-+ int len;
-+
-+ if (vif->bss_conf.nontransmitted)
-+ return 0;
-
- rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
-- MT7996_INBAND_FRAME_SIZE);
-+ MT7996_MAX_BSS_OFFLOAD_SIZE);
- if (IS_ERR(rskb))
- return PTR_ERR(rskb);
-
-@@ -2349,7 +2354,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
- if (!skb)
- return -EINVAL;
-
-- if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) {
-+ if (skb->len > MT7996_MAX_BEACON_SIZE) {
- dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
- dev_kfree_skb(skb);
- return -EINVAL;
-@@ -2360,7 +2365,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
- info->band = band;
- info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
-
-- tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov));
-+ len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
-+
-+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
-
- discov = (struct bss_inband_discovery_tlv *)tlv;
- discov->tx_mode = OFFLOAD_TX_MODE_SU;
-@@ -2371,7 +2378,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
- discov->enable = true;
- discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
-
-- buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
-+ buf = (u8 *)tlv + sizeof(*discov);
-
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
-
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 4ba06d9..eed7371 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -308,8 +308,6 @@ struct bss_inband_discovery_tlv {
- u8 enable;
- __le16 wcid;
- __le16 prob_rsp_len;
--#define MAX_INBAND_FRAME_SIZE 512
-- u8 pkt[MAX_INBAND_FRAME_SIZE];
- } __packed;
-
- struct bss_bcn_content_tlv {
-@@ -321,8 +319,6 @@ struct bss_bcn_content_tlv {
- u8 enable;
- u8 type;
- __le16 pkt_len;
--#define MAX_BEACON_SIZE 512
-- u8 pkt[MAX_BEACON_SIZE];
- } __packed;
-
- struct bss_bcn_cntdwn_tlv {
-@@ -629,13 +625,14 @@ enum {
- sizeof(struct sta_rec_hdr_trans) + \
- sizeof(struct tlv))
-
-+#define MT7996_MAX_BEACON_SIZE 1342
- #define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \
- sizeof(struct bss_bcn_content_tlv) + \
-+ MT_TXD_SIZE + \
- sizeof(struct bss_bcn_cntdwn_tlv) + \
- sizeof(struct bss_bcn_mbss_tlv))
--
--#define MT7996_INBAND_FRAME_SIZE (sizeof(struct bss_req_hdr) + \
-- sizeof(struct bss_inband_discovery_tlv))
-+#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
-+ MT7996_BEACON_UPDATE_SIZE)
-
- enum {
- UNI_BAND_CONFIG_RADIO_ENABLE,
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch
new file mode 100644
index 0000000..7b88df9
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch
@@ -0,0 +1,97 @@
+From ee2e6d4d137cadf56c1c102d73761f76fd97a6ea Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Fri, 22 Sep 2023 10:32:37 +0800
+Subject: [PATCH 29/98] wifi: mt76: mt7996: add preamble puncture support for
+ mt7996
+
+Add support configure preamble puncture feature through mcu commands.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt76_connac_mcu.h | 1 +
+ mt7996/mcu.c | 30 ++++++++++++++++++++++++++++++
+ mt7996/mcu.h | 4 ++++
+ mt7996/mt7996.h | 2 ++
+ 4 files changed, 37 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 8562ca4..6fac67b 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1241,6 +1241,7 @@ enum {
+ MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
+ MCU_UNI_CMD_THERMAL = 0x35,
+ MCU_UNI_CMD_VOW = 0x37,
++ MCU_UNI_CMD_PP = 0x38,
+ MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
+ MCU_UNI_CMD_RRO = 0x57,
+ MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 39f76a0..60af1d4 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4308,3 +4308,33 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
+ &req, sizeof(req), false);
+ }
++
++int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, bool auto_mode,
++ u8 force_bitmap_ctrl, u16 bitmap)
++{
++ struct mt7996_dev *dev = phy->dev;
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++ bool mgmt_mode;
++ u8 band_idx;
++ u8 force_bitmap_ctrl;
++ bool auto_mode;
++ __le16 bitmap;
++ u8 _rsv2[2];
++ } __packed req = {
++ .tag = cpu_to_le16(UNI_CMD_PP_EN_CTRL),
++ .len = cpu_to_le16(sizeof(req) - 4),
++
++ .mgmt_mode = !auto_mode,
++ .band_idx = phy->mt76->band_idx,
++ .force_bitmap_ctrl = force_bitmap_ctrl,
++ .auto_mode = auto_mode,
++ .bitmap = cpu_to_le16(bitmap),
++ };
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP),
++ &req, sizeof(req), false);
++}
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 376931e..296acbd 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -845,6 +845,10 @@ enum {
+ MT7996_SEC_MODE_MAX,
+ };
+
++enum {
++ UNI_CMD_PP_EN_CTRL,
++};
++
+ #define MT7996_PATCH_SEC GENMASK(31, 24)
+ #define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8)
+ #define MT7996_PATCH_AES_KEY GENMASK(7, 0)
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 31fa2b5..c4d74a0 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -598,6 +598,8 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
++int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, bool auto_mode, u8 force_bitmap,
++ u16 bitmap);
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct dentry *dir);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch
new file mode 100644
index 0000000..0789ad2
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch
@@ -0,0 +1,26 @@
+From b1d7c2518edfcf9fe96a0231132449c2f924d1d6 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 6 Oct 2023 16:39:39 +0800
+Subject: [PATCH 30/98] wifi: mt76: mt7996: fix all sta info struct alignment
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mcu.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 296acbd..af7cd18 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -219,7 +219,7 @@ struct mt7996_mcu_all_sta_info_event {
+ u8 more;
+ u8 rsv2;
+ __le16 sta_num;
+- u8 rsv3[2];
++ u8 rsv3[4];
+
+ union {
+ struct all_sta_trx_rate rate[0];
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch
deleted file mode 100644
index 0669836..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 80a4f15fa3077ef5a340a4af5b12fda8d958c337 Mon Sep 17 00:00:00 2001
-From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Tue, 18 Apr 2023 19:49:45 +0800
-Subject: [PATCH 31/39] wifi: mt76: mt7996: fix memory leak.
-
-Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
----
- mt7996/mcu.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index a2c1e43..f98a48d 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2286,11 +2286,14 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
- return PTR_ERR(rskb);
-
- skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
-- if (!skb)
-+ if (!skb) {
-+ dev_kfree_skb(rskb);
- return -EINVAL;
-+ }
-
- if (skb->len > MT7996_MAX_BEACON_SIZE) {
- dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
-+ dev_kfree_skb(rskb);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
-@@ -2351,11 +2354,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
- skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
- }
-
-- if (!skb)
-+ if (!skb) {
-+ dev_kfree_skb(rskb);
- return -EINVAL;
-+ }
-
- if (skb->len > MT7996_MAX_BEACON_SIZE) {
- dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
-+ dev_kfree_skb(rskb);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch
new file mode 100644
index 0000000..8e716a0
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch
@@ -0,0 +1,111 @@
+From 274d96dc00990390f4e830452d9032471deacf33 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 6 Oct 2023 11:44:03 +0800
+Subject: [PATCH 31/98] wifi: mt76: mt7996: refine ampdu factor
+
+Firmware would parse ht/vht/he/eht cap to get correct ampdu parameters.
+---
+ mt76_connac_mcu.h | 4 +++-
+ mt7996/mcu.c | 44 ++++----------------------------------------
+ mt7996/mcu.h | 1 -
+ 3 files changed, 7 insertions(+), 42 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 6fac67b..ca2e573 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -298,7 +298,9 @@ struct sta_rec_ht {
+ __le16 tag;
+ __le16 len;
+ __le16 ht_cap;
+- u16 rsv;
++ __le16 ht_cap_ext;
++ u8 ampdu_param;
++ u8 _rsv[3];
+ } __packed;
+
+ struct sta_rec_vht {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 60af1d4..8b81644 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1195,6 +1195,10 @@ mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+
+ ht = (struct sta_rec_ht *)tlv;
+ ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);
++ ht->ampdu_param = u8_encode_bits(sta->deflink.ht_cap.ampdu_factor,
++ IEEE80211_HT_AMPDU_PARM_FACTOR) |
++ u8_encode_bits(sta->deflink.ht_cap.ampdu_density,
++ IEEE80211_HT_AMPDU_PARM_DENSITY);
+ }
+
+ static void
+@@ -1651,44 +1655,6 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+ bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
+ }
+
+-static void
+-mt7996_mcu_sta_phy_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+- struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+-{
+- struct sta_rec_phy *phy;
+- struct tlv *tlv;
+- u8 af = 0, mm = 0;
+-
+- if (!sta->deflink.ht_cap.ht_supported && !sta->deflink.he_6ghz_capa.capa)
+- return;
+-
+- tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy));
+-
+- phy = (struct sta_rec_phy *)tlv;
+- if (sta->deflink.ht_cap.ht_supported) {
+- af = sta->deflink.ht_cap.ampdu_factor;
+- mm = sta->deflink.ht_cap.ampdu_density;
+- }
+-
+- if (sta->deflink.vht_cap.vht_supported) {
+- u8 vht_af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+- sta->deflink.vht_cap.cap);
+-
+- af = max_t(u8, af, vht_af);
+- }
+-
+- if (sta->deflink.he_6ghz_capa.capa) {
+- af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+- IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
+- mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+- IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
+- }
+-
+- phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR, af) |
+- FIELD_PREP(IEEE80211_HT_AMPDU_PARM_DENSITY, mm);
+- phy->max_ampdu_len = af;
+-}
+-
+ static void
+ mt7996_mcu_sta_hdrt_tlv(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -2100,8 +2066,6 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+
+ /* tag order is in accordance with firmware dependency. */
+ if (sta) {
+- /* starec phy */
+- mt7996_mcu_sta_phy_tlv(dev, skb, vif, sta);
+ /* starec hdrt mode */
+ mt7996_mcu_sta_hdrt_tlv(dev, skb);
+ /* starec bfer */
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index af7cd18..ca16336 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -730,7 +730,6 @@ enum {
+ sizeof(struct sta_rec_uapsd) + \
+ sizeof(struct sta_rec_amsdu) + \
+ sizeof(struct sta_rec_bfee) + \
+- sizeof(struct sta_rec_phy) + \
+ sizeof(struct sta_rec_ra_uni) + \
+ sizeof(struct sta_rec_sec) + \
+ sizeof(struct sta_rec_ra_fixed_uni) + \
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch
deleted file mode 100644
index a88d36a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch
+++ /dev/null
@@ -1,219 +0,0 @@
-From d246d8300bcbf7dea19919d61df9d7553e21bd1b Mon Sep 17 00:00:00 2001
-From: "sujuan.chen" <sujuan.chen@mediatek.com>
-Date: Wed, 26 Apr 2023 15:37:23 +0800
-Subject: [PATCH 33/39] wifi: mt76: mt7996: disable wfdma tx/rx during SER
-
-Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
----
- dma.c | 6 ++++
- mt7996/dma.c | 79 ++++++++++++++++++++++++++++++-------------------
- mt7996/mac.c | 13 ++++++--
- mt7996/mt7996.h | 1 +
- 4 files changed, 65 insertions(+), 34 deletions(-)
-
-diff --git a/dma.c b/dma.c
-index 465190e..f2b1b2a 100644
---- a/dma.c
-+++ b/dma.c
-@@ -466,6 +466,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
- struct mt76_queue_buf buf = {};
- dma_addr_t addr;
-
-+ if (test_bit(MT76_MCU_RESET, &dev->phy.state))
-+ goto error;
-+
- if (q->queued + 1 >= q->ndesc - 1)
- goto error;
-
-@@ -507,6 +510,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
- dma_addr_t addr;
- u8 *txwi;
-
-+ if (test_bit(MT76_MCU_RESET, &dev->phy.state))
-+ goto free_skb;
-+
- t = mt76_get_txwi(dev);
- if (!t)
- goto free_skb;
-diff --git a/mt7996/dma.c b/mt7996/dma.c
-index fbedaac..6a21e3e 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -128,11 +128,55 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
- }
- }
-
--static int mt7996_dma_enable(struct mt7996_dev *dev)
-+void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- {
- u32 hif1_ofs = 0;
- u32 irq_mask;
-
-+ if (dev->hif2)
-+ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-+
-+ /* enable wpdma tx/rx */
-+ if (!reset) {
-+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
-+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
-+
-+ if (dev->hif2)
-+ mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
-+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
-+ }
-+
-+ /* enable interrupts for TX/RX rings */
-+ irq_mask = MT_INT_MCU_CMD;
-+ if (reset)
-+ goto done;
-+
-+ irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
-+
-+ if (!dev->mphy.band_idx)
-+ irq_mask |= MT_INT_BAND0_RX_DONE;
-+
-+ if (dev->dbdc_support)
-+ irq_mask |= MT_INT_BAND1_RX_DONE;
-+
-+ if (dev->tbtc_support)
-+ irq_mask |= MT_INT_BAND2_RX_DONE;
-+
-+done:
-+ mt7996_irq_enable(dev, irq_mask);
-+ mt7996_irq_disable(dev, 0);
-+}
-+
-+static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
-+{
-+ u32 hif1_ofs = 0;
-+
- if (dev->hif2)
- hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-
-@@ -170,13 +214,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
- mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC,
- MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000);
-
-- /* set WFDMA Tx/Rx */
-- mt76_set(dev, MT_WFDMA0_GLO_CFG,
-- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
--
- /* GLO_CFG_EXT0 */
- mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0,
- WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
-@@ -187,12 +224,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
- WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
-
- if (dev->hif2) {
-- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
-- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
--
- /* GLO_CFG_EXT0 */
- mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
- WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
-@@ -216,21 +247,7 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
- /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
- }
-
-- /* enable interrupts for TX/RX rings */
-- irq_mask = MT_INT_RX_DONE_MCU |
-- MT_INT_TX_DONE_MCU |
-- MT_INT_MCU_CMD;
--
-- if (!dev->mphy.band_idx)
-- irq_mask |= MT_INT_BAND0_RX_DONE;
--
-- if (dev->dbdc_support)
-- irq_mask |= MT_INT_BAND1_RX_DONE;
--
-- if (dev->tbtc_support)
-- irq_mask |= MT_INT_BAND2_RX_DONE;
--
-- mt7996_irq_enable(dev, irq_mask);
-+ __mt7996_dma_enable(dev, reset);
-
- return 0;
- }
-@@ -347,7 +364,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- mt7996_poll_tx);
- napi_enable(&dev->mt76.tx_napi);
-
-- mt7996_dma_enable(dev);
-+ mt7996_dma_enable(dev, false);
-
- return 0;
- }
-@@ -413,7 +430,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
- mt76_for_each_q_rx(&dev->mt76, i)
- mt76_queue_rx_reset(dev, i);
-
-- mt7996_dma_enable(dev);
-+ mt7996_dma_enable(dev, !force);
- }
-
- void mt7996_dma_cleanup(struct mt7996_dev *dev)
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index bddb84f..986031f 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -2028,6 +2028,12 @@ void mt7996_mac_reset_work(struct work_struct *work)
- mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
- }
-
-+ mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
-+ mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
-+
-+ /* enable dma tx/rx and interrupt */
-+ __mt7996_dma_enable(dev, false);
-+
- clear_bit(MT76_MCU_RESET, &dev->mphy.state);
- clear_bit(MT76_RESET, &dev->mphy.state);
- if (phy2)
-@@ -2044,9 +2050,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
-
- tasklet_schedule(&dev->mt76.irq_tasklet);
-
-- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
-- mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
--
- mt76_worker_enable(&dev->mt76.tx_worker);
-
- local_bh_disable();
-@@ -2149,6 +2152,10 @@ skip_coredump:
-
- void mt7996_reset(struct mt7996_dev *dev)
- {
-+ dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n",
-+ wiphy_name(dev->mt76.hw->wiphy),
-+ READ_ONCE(dev->recovery.state));
-+
- if (!dev->recovery.hw_init_done)
- return;
-
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 8e5b3c3..561c1cd 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -448,6 +448,7 @@ int mt7996_dma_init(struct mt7996_dev *dev);
- void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
- void mt7996_dma_prefetch(struct mt7996_dev *dev);
- void mt7996_dma_cleanup(struct mt7996_dev *dev);
-+void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset);
- void mt7996_init_txpower(struct mt7996_dev *dev,
- struct ieee80211_supported_band *sband);
- int mt7996_txbf_init(struct mt7996_dev *dev);
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch
deleted file mode 100644
index 10bbe3a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 39893cc863213984a9ab0ae279dbfe433a6fe90e Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Tue, 23 May 2023 21:18:59 +0800
-Subject: [PATCH 38/39] wifi: mt76: mt7996: fix DFS CAC tx emission issue after
- 2nd interface up
-
-FW's channel state is set during the first wifi interface setup. If the switch reason for
-setting the tx/rx path during second-time wifi interface setup is CH_SWITCH_NORMAL,
-then the FW would perform runtime dpd channel calibration during DFS CAC, which leads to
-tx emission. Therefore, in order to bypass tx calibration during DFS CAC, set the switch reason
-to CH_SWITCH_DFS whenever chandef is set to DFS channel.
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- mt7996/mcu.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index b34c6b7..be5c908 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -3211,12 +3211,12 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
- .channel_band = ch_band[chandef->chan->band],
- };
-
-- if (tag == UNI_CHANNEL_RX_PATH ||
-- dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
-+ if (dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
- req.switch_reason = CH_SWITCH_NORMAL;
- else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
- req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
-- else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
-+ else if (cfg80211_chandef_valid(chandef) &&
-+ !cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
- NL80211_IFTYPE_AP))
- req.switch_reason = CH_SWITCH_DFS;
- else
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch
deleted file mode 100644
index b5a49a5..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From da1c93b8c6480cfcd605cd8c19111a6df8c9f8b4 Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Fri, 2 Jun 2023 15:12:34 +0800
-Subject: [PATCH] wifi: mt76: mt7996: fix beamformee ss subfield in EHT PHY
- caps IE
-
-According to P802.11be_D2.1 Table 9-401I, the minimum value of Beamformee SS shall
-be 3. Fix it to ensure that the value of Beamformee SS subfield is at least 3.
-
-Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
----
- mt7996/init.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 9eba689a..96c4bb01 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -936,16 +936,17 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
- IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
- IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
-
-+ val = max_t(u8, sts - 1, 3);
- eht_cap_elem->phy_cap_info[0] |=
-- u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
-+ u8_encode_bits(u8_get_bits(val, BIT(0)),
- IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
-
- eht_cap_elem->phy_cap_info[1] =
-- u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),
-+ u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)),
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |
-- u8_encode_bits(sts - 1,
-+ u8_encode_bits(val,
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) |
-- u8_encode_bits(sts - 1,
-+ u8_encode_bits(val,
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
-
- eht_cap_elem->phy_cap_info[2] =
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
index cb5d3bb..48ca34e 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
@@ -1,7 +1,7 @@
-From 83bb8ec37f85161b08f4eb2abf6a9a0530cfc189 Mon Sep 17 00:00:00 2001
+From fd11038a011cf006ee347a48d880c38a2ad20c75 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 3 Nov 2022 00:27:17 +0800
-Subject: [PATCH 0999/1015] wifi: mt76: mt7996: for build pass
+Subject: [PATCH 32/98] wifi: mt76: mt7996: for build pass
Change-Id: Ieb44c33ee6e6a2e6058c1ef528404c1a1cbcfdaf
---
@@ -18,7 +18,7 @@
10 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/debugfs.c b/debugfs.c
-index 79064a4d..e10d4cbc 100644
+index c4649ba..ac5207e 100644
--- a/debugfs.c
+++ b/debugfs.c
@@ -33,8 +33,11 @@ mt76_napi_threaded_set(void *data, u64 val)
@@ -34,10 +34,10 @@
return 0;
}
diff --git a/dma.c b/dma.c
-index f2b1b2ac..e1e9062b 100644
+index dd20271..bb995e2 100644
--- a/dma.c
+++ b/dma.c
-@@ -859,7 +859,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -943,7 +943,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
!(dev->drv->rx_check(dev, data, len)))
goto free_frag;
@@ -47,10 +47,10 @@
goto free_frag;
diff --git a/eeprom.c b/eeprom.c
-index 263e5089..aa889258 100644
+index 2558788..a07ca84 100644
--- a/eeprom.c
+++ b/eeprom.c
-@@ -108,9 +108,15 @@ void
+@@ -161,9 +161,15 @@ void
mt76_eeprom_override(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
@@ -68,7 +68,7 @@
if (!is_valid_ether_addr(phy->macaddr)) {
eth_random_addr(phy->macaddr);
diff --git a/mcu.c b/mcu.c
-index a8cafa39..fa4b0544 100644
+index a8cafa3..fa4b054 100644
--- a/mcu.c
+++ b/mcu.c
@@ -4,6 +4,7 @@
@@ -80,7 +80,7 @@
struct sk_buff *
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
diff --git a/mt7615/mcu.c b/mt7615/mcu.c
-index 8d745c97..86061e95 100644
+index 955974a..db337aa 100644
--- a/mt7615/mcu.c
+++ b/mt7615/mcu.c
@@ -10,6 +10,7 @@
@@ -92,7 +92,7 @@
static bool prefer_offload_fw = true;
module_param(prefer_offload_fw, bool, 0644);
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 5fab6772..c24dac10 100644
+index bb570f2..236cfea 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -4,6 +4,7 @@
@@ -104,7 +104,7 @@
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
{
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index aa706ff6..e8c1e572 100644
+index b6fba1a..dee01e0 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -6,6 +6,7 @@
@@ -116,10 +116,10 @@
#define fw_name(_dev, name, ...) ({ \
char *_fw; \
diff --git a/mt7996/dma.c b/mt7996/dma.c
-index f01cea5e..b8f253d0 100644
+index 1ed91da..23f6f16 100644
--- a/mt7996/dma.c
+++ b/mt7996/dma.c
-@@ -360,8 +360,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+@@ -602,8 +602,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
if (ret < 0)
return ret;
@@ -131,10 +131,10 @@
mt7996_dma_enable(dev, false);
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 9840c77d..b81ed64c 100644
+index ca0e9d0..7ae92e1 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
-@@ -121,6 +121,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
+@@ -98,6 +98,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
if (ret)
return ret;
@@ -143,7 +143,7 @@
dev->has_eht = !(cap & MODE_HE_ONLY);
dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 871d32a4..58893348 100644
+index 8b81644..fdc4fb4 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -5,6 +5,7 @@
@@ -155,5 +155,5 @@
#include "mcu.h"
#include "mac.h"
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
index fcc450e..d29a90b 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
@@ -1,45 +1,46 @@
-From 16ea1c12d369ea1f315edcc7a8525efc6d78403a Mon Sep 17 00:00:00 2001
+From 393f2e0f06e9a6ead8ffd64c904b6e24ff6c92f1 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Fri, 24 Mar 2023 14:02:32 +0800
-Subject: [PATCH] wifi: mt76: mt7996: add debug tool
+Subject: [PATCH 33/98] wifi: mt76: mt7996: add debug tool
Change-Id: Ie10390b01f17db893dbfbf3221bf63a4bd1fe38f
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
- mt7996/Makefile | 3 +
+ mt7996/Makefile | 4 +
mt7996/coredump.c | 10 +-
mt7996/coredump.h | 7 +
- mt7996/debugfs.c | 24 +-
- mt7996/mt7996.h | 14 +
- mt7996/mtk_debug.h | 2165 ++++++++++++++++++++++++++++++++++++++
- mt7996/mtk_debugfs.c | 2353 ++++++++++++++++++++++++++++++++++++++++++
+ mt7996/debugfs.c | 34 +-
+ mt7996/mt7996.h | 10 +
+ mt7996/mtk_debug.h | 2147 ++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_debugfs.c | 2379 ++++++++++++++++++++++++++++++++++++++++++
mt7996/mtk_mcu.c | 18 +
mt7996/mtk_mcu.h | 16 +
tools/fwlog.c | 25 +-
- 10 files changed, 4617 insertions(+), 18 deletions(-)
+ 10 files changed, 4630 insertions(+), 20 deletions(-)
create mode 100644 mt7996/mtk_debug.h
create mode 100644 mt7996/mtk_debugfs.c
create mode 100644 mt7996/mtk_mcu.c
create mode 100644 mt7996/mtk_mcu.h
diff --git a/mt7996/Makefile b/mt7996/Makefile
-index 7c2514a6..df131869 100644
+index 07c8b55..a056b40 100644
--- a/mt7996/Makefile
+++ b/mt7996/Makefile
-@@ -1,5 +1,6 @@
+@@ -1,4 +1,6 @@
# SPDX-License-Identifier: ISC
- EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
++EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
+EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
obj-$(CONFIG_MT7996E) += mt7996e.o
-@@ -9,3 +10,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
- mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
+@@ -6,3 +8,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
+ debugfs.o mmio.o
- mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
+ mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
+
+mt7996e-y += mtk_debugfs.o mtk_mcu.o
diff --git a/mt7996/coredump.c b/mt7996/coredump.c
-index 60b88085..a7f91b56 100644
+index 60b8808..a7f91b5 100644
--- a/mt7996/coredump.c
+++ b/mt7996/coredump.c
@@ -195,7 +195,7 @@ mt7996_coredump_fw_stack(struct mt7996_dev *dev, u8 type, struct mt7996_coredump
@@ -88,7 +89,7 @@
dev_warn(dev->mt76.dev, "no crash dump data found\n");
return -ENODATA;
diff --git a/mt7996/coredump.h b/mt7996/coredump.h
-index 01ed3731..93cd84a0 100644
+index 01ed373..93cd84a 100644
--- a/mt7996/coredump.h
+++ b/mt7996/coredump.h
@@ -75,6 +75,7 @@ struct mt7996_mem_region {
@@ -113,10 +114,21 @@
mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
{
diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index ca4d615d..93581fef 100644
+index 9bd9535..92aa164 100644
--- a/mt7996/debugfs.c
+++ b/mt7996/debugfs.c
-@@ -301,6 +301,9 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
+@@ -290,11 +290,20 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
+ DEBUG_SPL,
+ DEBUG_RPT_RX,
+ DEBUG_RPT_RA = 68,
++ DEBUG_IDS_PP = 93,
++ DEBUG_IDS_RA = 94,
++ DEBUG_IDS_BF = 95,
++ DEBUG_IDS_SR = 96,
++ DEBUG_IDS_RU = 97,
++ DEBUG_IDS_MUMIMO = 98,
+ } debug;
+ bool tx, rx, en;
int ret;
dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
@@ -126,7 +138,18 @@
if (dev->fw_debug_bin)
val = MCU_FW_LOG_RELAY;
-@@ -407,11 +410,12 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
+@@ -309,8 +318,8 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
+ if (ret)
+ return ret;
+
+- for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RA; debug++) {
+- if (debug == 67)
++ for (debug = DEBUG_TXCMD; debug <= DEBUG_IDS_MUMIMO; debug++) {
++ if (debug == 67 || (debug > DEBUG_RPT_RA && debug < DEBUG_IDS_PP))
+ continue;
+
+ if (debug == DEBUG_RPT_RX)
+@@ -401,11 +410,12 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
};
struct mt7996_dev *dev = data;
@@ -142,7 +165,7 @@
dev->fw_debug_bin = val;
-@@ -825,6 +829,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+@@ -819,6 +829,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
if (phy == &dev->phy)
dev->debugfs_dir = dir;
@@ -154,7 +177,7 @@
return 0;
}
-@@ -837,6 +846,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
+@@ -831,6 +846,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
void *dest;
spin_lock_irqsave(&lock, flags);
@@ -167,7 +190,7 @@
dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
if (dest) {
*(u32 *)dest = hdrlen + len;
-@@ -869,9 +884,6 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
+@@ -863,9 +884,6 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
.msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR),
};
@@ -178,11 +201,11 @@
hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0)));
hdr.len = *(__le16 *)data;
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 286fc1eb..6c76ec20 100644
+index c4d74a0..8801956 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -363,6 +363,16 @@ struct mt7996_dev {
- u32 reg_l2_backup;
+@@ -317,6 +317,16 @@ struct mt7996_dev {
+ spinlock_t reg_lock;
u8 wtbl_size_group;
+
@@ -198,21 +221,12 @@
};
enum {
-@@ -659,4 +669,8 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct dentry *dir);
- #endif
-
-+#ifdef CONFIG_MTK_DEBUG
-+int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
-+#endif
-+
- #endif
diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
new file mode 100644
-index 00000000..eb40f9cb
+index 0000000..368f0bc
--- /dev/null
+++ b/mt7996/mtk_debug.h
-@@ -0,0 +1,2165 @@
+@@ -0,0 +1,2147 @@
+#ifndef __MTK_DEBUG_H
+#define __MTK_DEBUG_H
+
@@ -289,23 +303,23 @@
+#define BN0_WF_AGG_TOP_TWTEDTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xe4) // 20E4
+#define BN0_WF_AGG_TOP_TWTEETB_ADDR (BN0_WF_AGG_TOP_BASE + 0xe8) // 20E8
+#define BN0_WF_AGG_TOP_TWTEFTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xec) // 20EC
-+#define BN0_WF_AGG_TOP_AALCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0xf0) // 20F0
-+#define BN0_WF_AGG_TOP_AALCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0xf4) // 20F4
-+#define BN0_WF_AGG_TOP_AALCR4_ADDR (BN0_WF_AGG_TOP_BASE + 0xf8) // 20F8
-+#define BN0_WF_AGG_TOP_AALCR5_ADDR (BN0_WF_AGG_TOP_BASE + 0xfc) // 20FC
-+#define BN0_WF_AGG_TOP_AALCR6_ADDR (BN0_WF_AGG_TOP_BASE + 0x100) // 2100
-+#define BN0_WF_AGG_TOP_AALCR7_ADDR (BN0_WF_AGG_TOP_BASE + 0x104) // 2104
+#define BN0_WF_AGG_TOP_ATCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x108) // 2108
+#define BN0_WF_AGG_TOP_ATCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x10c) // 210C
+#define BN0_WF_AGG_TOP_TCCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x110) // 2110
+#define BN0_WF_AGG_TOP_TFCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x114) // 2114
+#define BN0_WF_AGG_TOP_MUCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x118) // 2118
+#define BN0_WF_AGG_TOP_MUCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x11c) // 211C
-+#define BN0_WF_AGG_TOP_CSDCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x120) // 2120
-+#define BN0_WF_AGG_TOP_CSDCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x124) // 2124
-+#define BN0_WF_AGG_TOP_CSDCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x128) // 2128
-+#define BN0_WF_AGG_TOP_CSDCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x12c) // 212C
-+#define BN0_WF_AGG_TOP_CSDCR4_ADDR (BN0_WF_AGG_TOP_BASE + 0x130) // 2130
++#define BN0_WF_AGG_TOP_AALCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x128) // 2128
++#define BN0_WF_AGG_TOP_AALCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x12c) // 212C
++#define BN0_WF_AGG_TOP_AALCR4_ADDR (BN0_WF_AGG_TOP_BASE + 0x130) // 2130
++#define BN0_WF_AGG_TOP_AALCR5_ADDR (BN0_WF_AGG_TOP_BASE + 0x134) // 2134
++#define BN0_WF_AGG_TOP_AALCR6_ADDR (BN0_WF_AGG_TOP_BASE + 0x138) // 2138
++#define BN0_WF_AGG_TOP_AALCR7_ADDR (BN0_WF_AGG_TOP_BASE + 0x13c) // 213C
++#define BN0_WF_AGG_TOP_CSDCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x150) // 2150
++#define BN0_WF_AGG_TOP_CSDCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x154) // 2154
++#define BN0_WF_AGG_TOP_CSDCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x158) // 2158
++#define BN0_WF_AGG_TOP_CSDCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x15c) // 215C
++#define BN0_WF_AGG_TOP_CSDCR4_ADDR (BN0_WF_AGG_TOP_BASE + 0x160) // 2160
+#define BN0_WF_AGG_TOP_DYNSCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x178) // 2178
+#define BN0_WF_AGG_TOP_DYNSSCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x198) // 2198
+#define BN0_WF_AGG_TOP_TCDCNT0_ADDR (BN0_WF_AGG_TOP_BASE + 0x2c8) // 22C8
@@ -912,22 +926,22 @@
+#define BN0_WF_MIB_TOP_TRARC6_ADDR (BN0_WF_MIB_TOP_BASE + 0x0C8) // D0C8
+#define BN0_WF_MIB_TOP_TRARC7_ADDR (BN0_WF_MIB_TOP_BASE + 0x0CC) // D0CC
+
-+#define BN0_WF_MIB_TOP_TRDR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x9B4) // D9B4
-+#define BN0_WF_MIB_TOP_TRDR1_ADDR (BN0_WF_MIB_TOP_BASE + 0x9B8) // D9B8
-+#define BN0_WF_MIB_TOP_TRDR2_ADDR (BN0_WF_MIB_TOP_BASE + 0x9BC) // D9BC
-+#define BN0_WF_MIB_TOP_TRDR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x9C0) // D9C0
-+#define BN0_WF_MIB_TOP_TRDR4_ADDR (BN0_WF_MIB_TOP_BASE + 0x9C4) // D9C4
-+#define BN0_WF_MIB_TOP_TRDR5_ADDR (BN0_WF_MIB_TOP_BASE + 0x9C8) // D9C8
-+#define BN0_WF_MIB_TOP_TRDR6_ADDR (BN0_WF_MIB_TOP_BASE + 0x9CC) // D9CC
-+#define BN0_WF_MIB_TOP_TRDR7_ADDR (BN0_WF_MIB_TOP_BASE + 0x9D0) // D9D0
-+#define BN0_WF_MIB_TOP_TRDR8_ADDR (BN0_WF_MIB_TOP_BASE + 0x9D4) // D9D4
-+#define BN0_WF_MIB_TOP_TRDR9_ADDR (BN0_WF_MIB_TOP_BASE + 0x9D8) // D9D8
-+#define BN0_WF_MIB_TOP_TRDR10_ADDR (BN0_WF_MIB_TOP_BASE + 0x9DC) // D9DC
-+#define BN0_WF_MIB_TOP_TRDR11_ADDR (BN0_WF_MIB_TOP_BASE + 0x9E0) // D9E0
-+#define BN0_WF_MIB_TOP_TRDR12_ADDR (BN0_WF_MIB_TOP_BASE + 0x9E4) // D9E4
-+#define BN0_WF_MIB_TOP_TRDR13_ADDR (BN0_WF_MIB_TOP_BASE + 0x9E8) // D9E8
-+#define BN0_WF_MIB_TOP_TRDR14_ADDR (BN0_WF_MIB_TOP_BASE + 0x9EC) // D9EC
-+#define BN0_WF_MIB_TOP_TRDR15_ADDR (BN0_WF_MIB_TOP_BASE + 0x9F0) // D9F0
++#define BN0_WF_MIB_TOP_TRDR0_ADDR (BN0_WF_MIB_TOP_BASE + 0xA24) // DA24
++#define BN0_WF_MIB_TOP_TRDR1_ADDR (BN0_WF_MIB_TOP_BASE + 0xA28) // DA28
++#define BN0_WF_MIB_TOP_TRDR2_ADDR (BN0_WF_MIB_TOP_BASE + 0xA2C) // DA2C
++#define BN0_WF_MIB_TOP_TRDR3_ADDR (BN0_WF_MIB_TOP_BASE + 0xA30) // DA30
++#define BN0_WF_MIB_TOP_TRDR4_ADDR (BN0_WF_MIB_TOP_BASE + 0xA34) // DA34
++#define BN0_WF_MIB_TOP_TRDR5_ADDR (BN0_WF_MIB_TOP_BASE + 0xA38) // DA38
++#define BN0_WF_MIB_TOP_TRDR6_ADDR (BN0_WF_MIB_TOP_BASE + 0xA3C) // DA3C
++#define BN0_WF_MIB_TOP_TRDR7_ADDR (BN0_WF_MIB_TOP_BASE + 0xA40) // DA40
++#define BN0_WF_MIB_TOP_TRDR8_ADDR (BN0_WF_MIB_TOP_BASE + 0xA44) // DA44
++#define BN0_WF_MIB_TOP_TRDR9_ADDR (BN0_WF_MIB_TOP_BASE + 0xA48) // DA48
++#define BN0_WF_MIB_TOP_TRDR10_ADDR (BN0_WF_MIB_TOP_BASE + 0xA4C) // DA4C
++#define BN0_WF_MIB_TOP_TRDR11_ADDR (BN0_WF_MIB_TOP_BASE + 0xA50) // DA50
++#define BN0_WF_MIB_TOP_TRDR12_ADDR (BN0_WF_MIB_TOP_BASE + 0xA54) // DA54
++#define BN0_WF_MIB_TOP_TRDR13_ADDR (BN0_WF_MIB_TOP_BASE + 0xA58) // DA58
++#define BN0_WF_MIB_TOP_TRDR14_ADDR (BN0_WF_MIB_TOP_BASE + 0xA5C) // DA5C
++#define BN0_WF_MIB_TOP_TRDR15_ADDR (BN0_WF_MIB_TOP_BASE + 0xA60) // DA60
+
+#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_ADDR BN0_WF_MIB_TOP_TRARC0_ADDR
+#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_MASK 0x03FF0000 // AGG_RANG_SEL_1[25..16]
@@ -1178,6 +1192,10 @@
+#define WF_UWTBL_AMSDU_CFG_ADDR 32
+#define WF_UWTBL_AMSDU_CFG_MASK 0x00000fff // 11- 0
+#define WF_UWTBL_AMSDU_CFG_SHIFT 0
++#define WF_UWTBL_SEC_ADDR_MODE_DW 8
++#define WF_UWTBL_SEC_ADDR_MODE_ADDR 32
++#define WF_UWTBL_SEC_ADDR_MODE_MASK 0x00300000 // 21-20
++#define WF_UWTBL_SEC_ADDR_MODE_SHIFT 20
+#define WF_UWTBL_WMM_Q_DW 8
+#define WF_UWTBL_WMM_Q_ADDR 32
+#define WF_UWTBL_WMM_Q_MASK 0x06000000 // 26-25
@@ -1405,6 +1423,11 @@
+#define WF_LWTBL_ULPF_MASK \
+ 0x02000000 // 25-25
+#define WF_LWTBL_ULPF_SHIFT 25
++#define WF_LWTBL_BYPASS_TXSMM_DW 3
++#define WF_LWTBL_BYPASS_TXSMM_ADDR 12
++#define WF_LWTBL_BYPASS_TXSMM_MASK \
++ 0x04000000 // 26-26
++#define WF_LWTBL_BYPASS_TXSMM_SHIFT 26
+#define WF_LWTBL_TBF_HT_DW 3
+#define WF_LWTBL_TBF_HT_ADDR 12
+#define WF_LWTBL_TBF_HT_MASK \
@@ -1431,46 +1454,46 @@
+ 0x80000000 // 31-31
+#define WF_LWTBL_IGN_FBK_SHIFT 31
+// DW4
-+#define WF_LWTBL_ANT_ID0_DW 4
-+#define WF_LWTBL_ANT_ID0_ADDR 16
-+#define WF_LWTBL_ANT_ID0_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE0_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE0_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE0_MASK \
+ 0x00000007 // 2- 0
-+#define WF_LWTBL_ANT_ID0_SHIFT 0
-+#define WF_LWTBL_ANT_ID1_DW 4
-+#define WF_LWTBL_ANT_ID1_ADDR 16
-+#define WF_LWTBL_ANT_ID1_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT 0
++#define WF_LWTBL_NEGOTIATED_WINSIZE1_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE1_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE1_MASK \
+ 0x00000038 // 5- 3
-+#define WF_LWTBL_ANT_ID1_SHIFT 3
-+#define WF_LWTBL_ANT_ID2_DW 4
-+#define WF_LWTBL_ANT_ID2_ADDR 16
-+#define WF_LWTBL_ANT_ID2_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT 3
++#define WF_LWTBL_NEGOTIATED_WINSIZE2_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE2_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE2_MASK \
+ 0x000001c0 // 8- 6
-+#define WF_LWTBL_ANT_ID2_SHIFT 6
-+#define WF_LWTBL_ANT_ID3_DW 4
-+#define WF_LWTBL_ANT_ID3_ADDR 16
-+#define WF_LWTBL_ANT_ID3_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT 6
++#define WF_LWTBL_NEGOTIATED_WINSIZE3_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE3_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE3_MASK \
+ 0x00000e00 // 11- 9
-+#define WF_LWTBL_ANT_ID3_SHIFT 9
-+#define WF_LWTBL_ANT_ID4_DW 4
-+#define WF_LWTBL_ANT_ID4_ADDR 16
-+#define WF_LWTBL_ANT_ID4_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT 9
++#define WF_LWTBL_NEGOTIATED_WINSIZE4_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE4_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE4_MASK \
+ 0x00007000 // 14-12
-+#define WF_LWTBL_ANT_ID4_SHIFT 12
-+#define WF_LWTBL_ANT_ID5_DW 4
-+#define WF_LWTBL_ANT_ID5_ADDR 16
-+#define WF_LWTBL_ANT_ID5_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT 12
++#define WF_LWTBL_NEGOTIATED_WINSIZE5_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE5_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE5_MASK \
+ 0x00038000 // 17-15
-+#define WF_LWTBL_ANT_ID5_SHIFT 15
-+#define WF_LWTBL_ANT_ID6_DW 4
-+#define WF_LWTBL_ANT_ID6_ADDR 16
-+#define WF_LWTBL_ANT_ID6_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT 15
++#define WF_LWTBL_NEGOTIATED_WINSIZE6_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE6_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE6_MASK \
+ 0x001c0000 // 20-18
-+#define WF_LWTBL_ANT_ID6_SHIFT 18
-+#define WF_LWTBL_ANT_ID7_DW 4
-+#define WF_LWTBL_ANT_ID7_ADDR 16
-+#define WF_LWTBL_ANT_ID7_MASK \
++#define WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT 18
++#define WF_LWTBL_NEGOTIATED_WINSIZE7_DW 4
++#define WF_LWTBL_NEGOTIATED_WINSIZE7_ADDR 16
++#define WF_LWTBL_NEGOTIATED_WINSIZE7_MASK \
+ 0x00e00000 // 23-21
-+#define WF_LWTBL_ANT_ID7_SHIFT 21
++#define WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT 21
+#define WF_LWTBL_PE_DW 4
+#define WF_LWTBL_PE_ADDR 16
+#define WF_LWTBL_PE_MASK \
@@ -1501,6 +1524,11 @@
+#define WF_LWTBL_LDPC_EHT_MASK \
+ 0x40000000 // 30-30
+#define WF_LWTBL_LDPC_EHT_SHIFT 30
++#define WF_LWTBL_BA_MODE_DW 4
++#define WF_LWTBL_BA_MODE_ADDR 16
++#define WF_LWTBL_BA_MODE_MASK \
++ 0x80000000 // 31-31
++#define WF_LWTBL_BA_MODE_SHIFT 31
+// DW5
+#define WF_LWTBL_AF_DW 5
+#define WF_LWTBL_AF_ADDR 20
@@ -2087,46 +2115,15 @@
+ 0xffff0000 // 31-16
+#define WF_LWTBL_LINK_MGF_SHIFT 16
+// DW31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE0_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE0_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE0_MASK \
-+ 0x00000007 // 2- 0
-+#define WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT 0
-+#define WF_LWTBL_NEGOTIATED_WINSIZE1_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE1_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE1_MASK \
-+ 0x00000038 // 5- 3
-+#define WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT 3
-+#define WF_LWTBL_NEGOTIATED_WINSIZE2_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE2_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE2_MASK \
-+ 0x000001c0 // 8- 6
-+#define WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT 6
-+#define WF_LWTBL_NEGOTIATED_WINSIZE3_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE3_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE3_MASK \
-+ 0x00000e00 // 11- 9
-+#define WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT 9
-+#define WF_LWTBL_NEGOTIATED_WINSIZE4_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE4_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE4_MASK \
-+ 0x00007000 // 14-12
-+#define WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT 12
-+#define WF_LWTBL_NEGOTIATED_WINSIZE5_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE5_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE5_MASK \
-+ 0x00038000 // 17-15
-+#define WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT 15
-+#define WF_LWTBL_NEGOTIATED_WINSIZE6_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE6_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE6_MASK \
-+ 0x001c0000 // 20-18
-+#define WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT 18
-+#define WF_LWTBL_NEGOTIATED_WINSIZE7_DW 31
-+#define WF_LWTBL_NEGOTIATED_WINSIZE7_ADDR 124
-+#define WF_LWTBL_NEGOTIATED_WINSIZE7_MASK \
-+ 0x00e00000 // 23-21
-+#define WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT 21
++#define WF_LWTBL_BFTX_TB_DW 31
++#define WF_LWTBL_BFTX_TB_ADDR 124
++#define WF_LWTBL_BFTX_TB_MASK \
++ 0x00800000 // 23-23
++#define WF_LWTBL_DROP_DW 31
++#define WF_LWTBL_DROP_ADDR 124
++#define WF_LWTBL_DROP_MASK \
++ 0x01000000 // 24-24
++#define WF_LWTBL_DROP_SHIFT 24
+#define WF_LWTBL_CASCAD_DW 31
+#define WF_LWTBL_CASCAD_ADDR 124
+#define WF_LWTBL_CASCAD_MASK \
@@ -2142,42 +2139,37 @@
+#define WF_LWTBL_MPDU_SIZE_MASK \
+ 0x18000000 // 28-27
+#define WF_LWTBL_MPDU_SIZE_SHIFT 27
-+#define WF_LWTBL_BA_MODE_DW 31
-+#define WF_LWTBL_BA_MODE_ADDR 124
-+#define WF_LWTBL_BA_MODE_MASK \
-+ 0xe0000000 // 31-29
-+#define WF_LWTBL_BA_MODE_SHIFT 29
++#define WF_LWTBL_RXD_DUP_MODE_DW 31
++#define WF_LWTBL_RXD_DUP_MODE_ADDR 124
++#define WF_LWTBL_RXD_DUP_MODE_MASK \
++ 0x60000000 // 30-29
++#define WF_LWTBL_RXD_DUP_MODE_SHIFT 29
++#define WF_LWTBL_ACK_EN_DW 31
++#define WF_LWTBL_ACK_EN_ADDR 128
++#define WF_LWTBL_ACK_EN_MASK \
++ 0x80000000 // 31-31
++#define WF_LWTBL_ACK_EN_SHIFT 31
+// DW32
+#define WF_LWTBL_OM_INFO_DW 32
+#define WF_LWTBL_OM_INFO_ADDR 128
+#define WF_LWTBL_OM_INFO_MASK \
+ 0x00000fff // 11- 0
+#define WF_LWTBL_OM_INFO_SHIFT 0
++#define WF_LWTBL_OM_INFO_EHT_DW 32
++#define WF_LWTBL_OM_INFO_EHT_ADDR 128
++#define WF_LWTBL_OM_INFO_EHT_MASK \
++ 0x0000f000 // 15-12
++#define WF_LWTBL_OM_INFO_EHT_SHIFT 12
+#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_DW 32
+#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_ADDR 128
+#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_MASK \
-+ 0x00001000 // 12-12
-+#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_SHIFT 12
++ 0x00010000 // 16-16
++#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_SHIFT 16
+#define WF_LWTBL_RXD_DUP_WHITE_LIST_DW 32
+#define WF_LWTBL_RXD_DUP_WHITE_LIST_ADDR 128
+#define WF_LWTBL_RXD_DUP_WHITE_LIST_MASK \
-+ 0x01ffe000 // 24-13
-+#define WF_LWTBL_RXD_DUP_WHITE_LIST_SHIFT 13
-+#define WF_LWTBL_RXD_DUP_MODE_DW 32
-+#define WF_LWTBL_RXD_DUP_MODE_ADDR 128
-+#define WF_LWTBL_RXD_DUP_MODE_MASK \
-+ 0x06000000 // 26-25
-+#define WF_LWTBL_RXD_DUP_MODE_SHIFT 25
-+#define WF_LWTBL_DROP_DW 32
-+#define WF_LWTBL_DROP_ADDR 128
-+#define WF_LWTBL_DROP_MASK \
-+ 0x40000000 // 30-30
-+#define WF_LWTBL_DROP_SHIFT 30
-+#define WF_LWTBL_ACK_EN_DW 32
-+#define WF_LWTBL_ACK_EN_ADDR 128
-+#define WF_LWTBL_ACK_EN_MASK \
-+ 0x80000000 // 31-31
-+#define WF_LWTBL_ACK_EN_SHIFT 31
++ 0x1ffe0000 // 28-17
++#define WF_LWTBL_RXD_DUP_WHITE_LIST_SHIFT 17
+// DW33
+#define WF_LWTBL_USER_RSSI_DW 33
+#define WF_LWTBL_USER_RSSI_ADDR 132
@@ -2288,6 +2280,10 @@
+#define WTBL_AMSDU_EN_MASK BIT(11)
+#define WTBL_AMSDU_EN_OFFSET 11
+
++/* UWTBL DW 8 */
++#define WTBL_SEC_ADDR_MODE_MASK BITS(20, 21)
++#define WTBL_SEC_ADDR_MODE_OFFSET 20
++
+/* LWTBL Rate field */
+#define WTBL_RATE_TX_RATE_MASK BITS(0, 5)
+#define WTBL_RATE_TX_RATE_OFFSET 0
@@ -2380,10 +2376,10 @@
+#endif
diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
new file mode 100644
-index 00000000..f04c300f
+index 0000000..5aa5c94
--- /dev/null
+++ b/mt7996/mtk_debugfs.c
-@@ -0,0 +1,2353 @@
+@@ -0,0 +1,2379 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2023 MediaTek Inc.
@@ -2406,7 +2402,7 @@
+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
+ u64 total_burst, total_ampdu, ampdu_cnt[16];
+ u32 value, idx, row_idx, col_idx, start_range, agg_rang_sel[16], burst_cnt[16], band_offset = 0;
-+ u8 readFW = 0, partial_str[16] = {}, full_str[64] = {};
++ u8 partial_str[16] = {}, full_str[64] = {};
+
+ switch (band_idx) {
+ case 0:
@@ -2465,50 +2461,46 @@
+
+ seq_printf(s, "===AMPDU Related Counters===\n");
+
-+ if (readFW) {
-+ /* BELLWETHER TODO: Wait MIB counter API implement complete */
-+ } else {
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC0_ADDR + band_offset);
-+ agg_rang_sel[0] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_SHFT;
-+ agg_rang_sel[1] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC1_ADDR + band_offset);
-+ agg_rang_sel[2] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_SHFT;
-+ agg_rang_sel[3] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC2_ADDR + band_offset);
-+ agg_rang_sel[4] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_SHFT;
-+ agg_rang_sel[5] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC3_ADDR + band_offset);
-+ agg_rang_sel[6] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_SHFT;
-+ agg_rang_sel[7] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC4_ADDR + band_offset);
-+ agg_rang_sel[8] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_SHFT;
-+ agg_rang_sel[9] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC5_ADDR + band_offset);
-+ agg_rang_sel[10] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_SHFT;
-+ agg_rang_sel[11] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC6_ADDR + band_offset);
-+ agg_rang_sel[12] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_SHFT;
-+ agg_rang_sel[13] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_SHFT;
-+ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC7_ADDR + band_offset);
-+ agg_rang_sel[14] = (value & BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_MASK) >> BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC0_ADDR + band_offset);
++ agg_rang_sel[0] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_SHFT;
++ agg_rang_sel[1] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC1_ADDR + band_offset);
++ agg_rang_sel[2] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_SHFT;
++ agg_rang_sel[3] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC2_ADDR + band_offset);
++ agg_rang_sel[4] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_SHFT;
++ agg_rang_sel[5] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC3_ADDR + band_offset);
++ agg_rang_sel[6] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_SHFT;
++ agg_rang_sel[7] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC4_ADDR + band_offset);
++ agg_rang_sel[8] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_SHFT;
++ agg_rang_sel[9] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC5_ADDR + band_offset);
++ agg_rang_sel[10] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_SHFT;
++ agg_rang_sel[11] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC6_ADDR + band_offset);
++ agg_rang_sel[12] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_SHFT;
++ agg_rang_sel[13] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_SHFT;
++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC7_ADDR + band_offset);
++ agg_rang_sel[14] = (value & BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_MASK) >> BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_SHFT;
+
-+ burst_cnt[0] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR0_ADDR + band_offset);
-+ burst_cnt[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR1_ADDR + band_offset);
-+ burst_cnt[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR2_ADDR + band_offset);
-+ burst_cnt[3] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR3_ADDR + band_offset);
-+ burst_cnt[4] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR4_ADDR + band_offset);
-+ burst_cnt[5] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR5_ADDR + band_offset);
-+ burst_cnt[6] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR6_ADDR + band_offset);
-+ burst_cnt[7] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR7_ADDR + band_offset);
-+ burst_cnt[8] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR8_ADDR + band_offset);
-+ burst_cnt[9] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR9_ADDR + band_offset);
-+ burst_cnt[10] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR10_ADDR + band_offset);
-+ burst_cnt[11] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR11_ADDR + band_offset);
-+ burst_cnt[12] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR12_ADDR + band_offset);
-+ burst_cnt[13] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR13_ADDR + band_offset);
-+ burst_cnt[14] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR14_ADDR + band_offset);
-+ burst_cnt[15] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR15_ADDR + band_offset);
-+ }
++ burst_cnt[0] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR0_ADDR + band_offset);
++ burst_cnt[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR1_ADDR + band_offset);
++ burst_cnt[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR2_ADDR + band_offset);
++ burst_cnt[3] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR3_ADDR + band_offset);
++ burst_cnt[4] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR4_ADDR + band_offset);
++ burst_cnt[5] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR5_ADDR + band_offset);
++ burst_cnt[6] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR6_ADDR + band_offset);
++ burst_cnt[7] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR7_ADDR + band_offset);
++ burst_cnt[8] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR8_ADDR + band_offset);
++ burst_cnt[9] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR9_ADDR + band_offset);
++ burst_cnt[10] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR10_ADDR + band_offset);
++ burst_cnt[11] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR11_ADDR + band_offset);
++ burst_cnt[12] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR12_ADDR + band_offset);
++ burst_cnt[13] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR13_ADDR + band_offset);
++ burst_cnt[14] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR14_ADDR + band_offset);
++ burst_cnt[15] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR15_ADDR + band_offset);
+
+ start_range = 1;
+ total_burst = 0;
@@ -3455,7 +3447,8 @@
+ {"PFMU_IDX", WF_LWTBL_PFMU_IDX_MASK, WF_LWTBL_PFMU_IDX_SHIFT, false},
+ {"ULPF_IDX", WF_LWTBL_ULPF_IDX_MASK, WF_LWTBL_ULPF_IDX_SHIFT, false},
+ {"RIBF", WF_LWTBL_RIBF_MASK, NO_SHIFT_DEFINE, false},
-+ {"ULPF", WF_LWTBL_ULPF_MASK, NO_SHIFT_DEFINE, true},
++ {"ULPF", WF_LWTBL_ULPF_MASK, NO_SHIFT_DEFINE, false},
++ {"BYPASS_TXSMM", WF_LWTBL_BYPASS_TXSMM_MASK, NO_SHIFT_DEFINE, true},
+ {"TBF_HT", WF_LWTBL_TBF_HT_MASK, NO_SHIFT_DEFINE, false},
+ {"TBF_VHT", WF_LWTBL_TBF_VHT_MASK, NO_SHIFT_DEFINE, false},
+ {"TBF_HE", WF_LWTBL_TBF_HE_MASK, NO_SHIFT_DEFINE, false},
@@ -3489,20 +3482,21 @@
+}
+
+static const struct berse_wtbl_parse WTBL_LMAC_DW4[] = {
-+ {"ANT_ID_STS0", WF_LWTBL_ANT_ID0_MASK, WF_LWTBL_ANT_ID0_SHIFT, false},
-+ {"STS1", WF_LWTBL_ANT_ID1_MASK, WF_LWTBL_ANT_ID1_SHIFT, false},
-+ {"STS2", WF_LWTBL_ANT_ID2_MASK, WF_LWTBL_ANT_ID2_SHIFT, false},
-+ {"STS3", WF_LWTBL_ANT_ID3_MASK, WF_LWTBL_ANT_ID3_SHIFT, true},
-+ {"ANT_ID_STS4", WF_LWTBL_ANT_ID4_MASK, WF_LWTBL_ANT_ID4_SHIFT, false},
-+ {"STS5", WF_LWTBL_ANT_ID5_MASK, WF_LWTBL_ANT_ID5_SHIFT, false},
-+ {"STS6", WF_LWTBL_ANT_ID6_MASK, WF_LWTBL_ANT_ID6_SHIFT, false},
-+ {"STS7", WF_LWTBL_ANT_ID7_MASK, WF_LWTBL_ANT_ID7_SHIFT, true},
++ {"NEGOTIATED_WINSIZE0", WF_LWTBL_NEGOTIATED_WINSIZE0_MASK, WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT, false},
++ {"WINSIZE1", WF_LWTBL_NEGOTIATED_WINSIZE1_MASK, WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT, false},
++ {"WINSIZE2", WF_LWTBL_NEGOTIATED_WINSIZE2_MASK, WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT, false},
++ {"WINSIZE3", WF_LWTBL_NEGOTIATED_WINSIZE3_MASK, WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT, true},
++ {"WINSIZE4", WF_LWTBL_NEGOTIATED_WINSIZE4_MASK, WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT, false},
++ {"WINSIZE5", WF_LWTBL_NEGOTIATED_WINSIZE5_MASK, WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT, false},
++ {"WINSIZE6", WF_LWTBL_NEGOTIATED_WINSIZE6_MASK, WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT, false},
++ {"WINSIZE7", WF_LWTBL_NEGOTIATED_WINSIZE7_MASK, WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT, true},
+ {"PE", WF_LWTBL_PE_MASK, WF_LWTBL_PE_SHIFT, false},
+ {"DIS_RHTR", WF_LWTBL_DIS_RHTR_MASK, NO_SHIFT_DEFINE, false},
+ {"LDPC_HT", WF_LWTBL_LDPC_HT_MASK, NO_SHIFT_DEFINE, false},
+ {"LDPC_VHT", WF_LWTBL_LDPC_VHT_MASK, NO_SHIFT_DEFINE, false},
+ {"LDPC_HE", WF_LWTBL_LDPC_HE_MASK, NO_SHIFT_DEFINE, false},
+ {"LDPC_EHT", WF_LWTBL_LDPC_EHT_MASK, NO_SHIFT_DEFINE, true},
++ {"BA_MODE", WF_LWTBL_BA_MODE_MASK, NO_SHIFT_DEFINE, true},
+ {NULL,}
+};
+
@@ -3888,6 +3882,12 @@
+ {NULL,}
+};
+
++static const struct berse_wtbl_parse WTBL_LMAC_DW14[] = {
++ {"RATE1_TX_CNT", WF_LWTBL_RATE1_TX_CNT_MASK, WF_LWTBL_RATE1_TX_CNT_SHIFT, false},
++ {"RATE1_FAIL_CNT", WF_LWTBL_RATE1_FAIL_CNT_MASK, WF_LWTBL_RATE1_FAIL_CNT_SHIFT, true},
++ {NULL,}
++};
++
+static void parse_fmac_lwtbl_dw14(struct seq_file *s, u8 *lwtbl)
+{
+ u32 *addr, *muar_addr = 0;
@@ -3906,7 +3906,27 @@
+ dw_value = *addr;
+
+ while (WTBL_LMAC_DW14_BMC[i].name) {
-+ parse_rate(s, i+6, (dw_value & WTBL_LMAC_DW14_BMC[i].mask) >> WTBL_LMAC_DW14_BMC[i].shift);
++ if (WTBL_LMAC_DW14_BMC[i].shift == NO_SHIFT_DEFINE)
++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW14_BMC[i].name,
++ (dw_value & WTBL_LMAC_DW14_BMC[i].mask) ? 1 : 0);
++ else
++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW14_BMC[i].name,
++ (dw_value & WTBL_LMAC_DW14_BMC[i].mask) >> WTBL_LMAC_DW14_BMC[i].shift);
++ i++;
++ }
++ } else {
++ seq_printf(s, "\t\n");
++ seq_printf(s, "LWTBL DW 14\n");
++ addr = (u32 *)&(lwtbl[WF_LWTBL_CIPHER_SUIT_IGTK_DW*4]);
++ dw_value = *addr;
++
++ while (WTBL_LMAC_DW14[i].name) {
++ if (WTBL_LMAC_DW14[i].shift == NO_SHIFT_DEFINE)
++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW14[i].name,
++ (dw_value & WTBL_LMAC_DW14[i].mask) ? 1 : 0);
++ else
++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW14[i].name,
++ (dw_value & WTBL_LMAC_DW14[i].mask) >> WTBL_LMAC_DW14[i].shift);
+ i++;
+ }
+ }
@@ -3916,7 +3936,7 @@
+ {"RELATED_IDX0", WF_LWTBL_RELATED_IDX0_MASK, WF_LWTBL_RELATED_IDX0_SHIFT, false},
+ {"RELATED_BAND0", WF_LWTBL_RELATED_BAND0_MASK, WF_LWTBL_RELATED_BAND0_SHIFT, false},
+ {"PRI_MLD_BAND", WF_LWTBL_PRIMARY_MLD_BAND_MASK, WF_LWTBL_PRIMARY_MLD_BAND_SHIFT, true},
-+ {"RELATED_IDX0", WF_LWTBL_RELATED_IDX1_MASK, WF_LWTBL_RELATED_IDX1_SHIFT, false},
++ {"RELATED_IDX1", WF_LWTBL_RELATED_IDX1_MASK, WF_LWTBL_RELATED_IDX1_SHIFT, false},
+ {"RELATED_BAND1", WF_LWTBL_RELATED_BAND1_MASK, WF_LWTBL_RELATED_BAND1_SHIFT, false},
+ {"SEC_MLD_BAND", WF_LWTBL_SECONDARY_MLD_BAND_MASK, WF_LWTBL_SECONDARY_MLD_BAND_SHIFT, true},
+ {NULL,}
@@ -4022,18 +4042,13 @@
+}
+
+static const struct berse_wtbl_parse WTBL_LMAC_DW31[] = {
-+ {"NEGO_WINSIZE0", WF_LWTBL_NEGOTIATED_WINSIZE0_MASK, WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT, false},
-+ {"WINSIZE1", WF_LWTBL_NEGOTIATED_WINSIZE1_MASK, WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT, false},
-+ {"WINSIZE2", WF_LWTBL_NEGOTIATED_WINSIZE2_MASK, WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT, false},
-+ {"WINSIZE3", WF_LWTBL_NEGOTIATED_WINSIZE3_MASK, WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT, true},
-+ {"WINSIZE4", WF_LWTBL_NEGOTIATED_WINSIZE4_MASK, WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT, false},
-+ {"WINSIZE5", WF_LWTBL_NEGOTIATED_WINSIZE5_MASK, WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT, false},
-+ {"WINSIZE6", WF_LWTBL_NEGOTIATED_WINSIZE6_MASK, WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT, false},
-+ {"WINSIZE7", WF_LWTBL_NEGOTIATED_WINSIZE7_MASK, WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT, true},
++ {"BFTX_TB", WF_LWTBL_BFTX_TB_MASK, NO_SHIFT_DEFINE, false},
++ {"DROP", WF_LWTBL_DROP_MASK, NO_SHIFT_DEFINE, false},
+ {"CASCAD", WF_LWTBL_CASCAD_MASK, NO_SHIFT_DEFINE, false},
+ {"ALL_ACK", WF_LWTBL_ALL_ACK_MASK, NO_SHIFT_DEFINE, false},
+ {"MPDU_SIZE", WF_LWTBL_MPDU_SIZE_MASK, WF_LWTBL_MPDU_SIZE_SHIFT, false},
-+ {"BA_MODE", WF_LWTBL_BA_MODE_MASK, WF_LWTBL_BA_MODE_SHIFT, true},
++ {"RXD_DUP_MODE", WF_LWTBL_RXD_DUP_MODE_MASK, WF_LWTBL_RXD_DUP_MODE_SHIFT, true},
++ {"ACK_EN", WF_LWTBL_ACK_EN_MASK, NO_SHIFT_DEFINE, true},
+ {NULL,}
+};
+
@@ -4063,11 +4078,9 @@
+
+static const struct berse_wtbl_parse WTBL_LMAC_DW32[] = {
+ {"OM_INFO", WF_LWTBL_OM_INFO_MASK, WF_LWTBL_OM_INFO_SHIFT, false},
-+ {"OM_RXD_DUP_MODE", WF_LWTBL_RXD_DUP_FOR_OM_CHG_MASK, NO_SHIFT_DEFINE, false},
++ {"OM_INFO_EHT", WF_LWTBL_OM_INFO_EHT_MASK, WF_LWTBL_OM_INFO_EHT_SHIFT, false},
++ {"RXD_DUP_FOR_OM_CHG", WF_LWTBL_RXD_DUP_FOR_OM_CHG_MASK, NO_SHIFT_DEFINE, false},
+ {"RXD_DUP_WHITE_LIST", WF_LWTBL_RXD_DUP_WHITE_LIST_MASK, WF_LWTBL_RXD_DUP_WHITE_LIST_SHIFT, false},
-+ {"RXD_DUP_MODE", WF_LWTBL_RXD_DUP_MODE_MASK, WF_LWTBL_RXD_DUP_MODE_SHIFT, false},
-+ {"DROP", WF_LWTBL_DROP_MASK, NO_SHIFT_DEFINE, false},
-+ {"ACK_EN", WF_LWTBL_ACK_EN_MASK, NO_SHIFT_DEFINE, true},
+ {NULL,}
+};
+
@@ -4212,7 +4225,7 @@
+ {"RELATED_IDX0", WF_UWTBL_RELATED_IDX0_MASK, WF_UWTBL_RELATED_IDX0_SHIFT, false},
+ {"RELATED_BAND0", WF_UWTBL_RELATED_BAND0_MASK, WF_UWTBL_RELATED_BAND0_SHIFT, false},
+ {"PRI_MLD_BAND", WF_UWTBL_PRIMARY_MLD_BAND_MASK, WF_UWTBL_PRIMARY_MLD_BAND_SHIFT, true},
-+ {"RELATED_IDX0", WF_UWTBL_RELATED_IDX1_MASK, WF_UWTBL_RELATED_IDX1_SHIFT, false},
++ {"RELATED_IDX1", WF_UWTBL_RELATED_IDX1_MASK, WF_UWTBL_RELATED_IDX1_SHIFT, false},
+ {"RELATED_BAND1", WF_UWTBL_RELATED_BAND1_MASK, WF_UWTBL_RELATED_BAND1_SHIFT, false},
+ {"SEC_MLD_BAND", WF_UWTBL_SECONDARY_MLD_BAND_MASK, WF_UWTBL_SECONDARY_MLD_BAND_SHIFT, true},
+ {NULL,}
@@ -4287,6 +4300,7 @@
+static const struct berse_wtbl_parse WTBL_UMAC_DW3[] = {
+ {"PN4", WTBL_PN4_MASK, WTBL_PN4_OFFSET, false},
+ {"PN5", WTBL_PN5_MASK, WTBL_PN5_OFFSET, true},
++ {"COM_SN", WF_UWTBL_COM_SN_MASK, WF_UWTBL_COM_SN_SHIFT, true},
+ {NULL,}
+};
+
@@ -4299,8 +4313,8 @@
+};
+
+static const struct berse_wtbl_parse WTBL_UMAC_DW5_BIPN[] = {
-+ {"BIPN4", WTBL_BIPN0_MASK, WTBL_BIPN0_OFFSET, false},
-+ {"BIPN5", WTBL_BIPN1_MASK, WTBL_BIPN1_OFFSET, true},
++ {"BIPN4", WTBL_BIPN4_MASK, WTBL_BIPN4_OFFSET, false},
++ {"BIPN5", WTBL_BIPN5_MASK, WTBL_BIPN5_OFFSET, true},
+ {NULL,}
+};
+
@@ -4515,6 +4529,8 @@
+
+ /* UMAC WTBL DW 6 for BIGTK */
+ if (is_wtbl_bigtk_exist(lwtbl) == true) {
++ addr = (u32 *)&(uwtbl[WF_UWTBL_KEY_LOC2_DW*4]);
++ dw_value = *addr;
+ keyloc2 = (dw_value & WF_UWTBL_KEY_LOC2_MASK) >>
+ WF_UWTBL_KEY_LOC2_SHIFT;
+ seq_printf(s, "\t%s:%u\n", "Key Loc 2", keyloc2);
@@ -4558,6 +4574,12 @@
+ i++;
+ }
+
++ /* UMAC WTBL DW 8 - SEC_ADDR_MODE */
++ addr = (u32 *)&(uwtbl[WF_UWTBL_SEC_ADDR_MODE_DW*4]);
++ dw_value = *addr;
++ seq_printf(s, "\t%s:%lu\n", "SEC_ADDR_MODE",
++ (dw_value & WTBL_SEC_ADDR_MODE_MASK) >> WTBL_SEC_ADDR_MODE_OFFSET);
++
+ /* UMAC WTBL DW 8 - AMSDU_CFG */
+ seq_printf(s, "\t%s:%d\n", "HW AMSDU Enable",
+ (dw_value & WTBL_AMSDU_EN_MASK) ? 1 : 0);
@@ -4739,7 +4761,7 @@
+#endif
diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
new file mode 100644
-index 00000000..e8870166
+index 0000000..e887016
--- /dev/null
+++ b/mt7996/mtk_mcu.c
@@ -0,0 +1,18 @@
@@ -4763,7 +4785,7 @@
+#endif
diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
new file mode 100644
-index 00000000..e741aa27
+index 0000000..e741aa2
--- /dev/null
+++ b/mt7996/mtk_mcu.h
@@ -0,0 +1,16 @@
@@ -4784,7 +4806,7 @@
+
+#endif
diff --git a/tools/fwlog.c b/tools/fwlog.c
-index e5d4a105..3c6a61d7 100644
+index e5d4a10..3c6a61d 100644
--- a/tools/fwlog.c
+++ b/tools/fwlog.c
@@ -26,7 +26,7 @@ static const char *debugfs_path(const char *phyname, const char *file)
@@ -4868,5 +4890,5 @@
return ret;
}
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch
new file mode 100644
index 0000000..ff8d7a8
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch
@@ -0,0 +1,61 @@
+From cb64d3c0b0dd79b8255caef614b13fe17f1b5b07 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
+Date: Thu, 8 Jun 2023 17:32:33 +0800
+Subject: [PATCH 34/98] wifi: mt76: mt7996: add check for hostapd config
+ he_ldpc
+
+Add check for hostapd config he_ldpc.
+This capabilities is checked in mcu_beacon_check_caps in 7915.
+
+Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+Change-Id: I6d6f59df8897e3c00f2e0a1e3c6e5701e31c5e4b
+---
+ mt7996/mcu.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index fdc4fb4..7d0c511 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1096,7 +1096,8 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+ }
+
+ static void
+-mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
++mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
++ struct ieee80211_sta *sta)
+ {
+ struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
+ struct ieee80211_he_mcs_nss_supp mcs_map;
+@@ -1116,6 +1117,10 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ he->he_phy_cap[i] = elem->phy_cap_info[i];
+ }
+
++ if (vif->type == NL80211_IFTYPE_AP)
++ u8p_replace_bits(&he->he_phy_cap[1], vif->bss_conf.he_ldpc,
++ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD);
++
+ mcs_map = sta->deflink.he_cap.he_mcs_nss_supp;
+ switch (sta->deflink.bandwidth) {
+ case IEEE80211_STA_RX_BW_160:
+@@ -1994,7 +1999,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ * update sta_rec_he here.
+ */
+ if (changed)
+- mt7996_mcu_sta_he_tlv(skb, sta);
++ mt7996_mcu_sta_he_tlv(skb, vif, sta);
+
+ /* sta_rec_ra accommodates BW, NSS and only MCS range format
+ * i.e 0-{7,8,9} for VHT.
+@@ -2080,7 +2085,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ /* starec amsdu */
+ mt7996_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
+ /* starec he */
+- mt7996_mcu_sta_he_tlv(skb, sta);
++ mt7996_mcu_sta_he_tlv(skb, vif, sta);
+ /* starec he 6g*/
+ mt7996_mcu_sta_he_6g_tlv(skb, sta);
+ /* starec eht */
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
similarity index 86%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
index 686576d..56f85a8 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
@@ -1,7 +1,7 @@
-From 33211d380fbf3b0892e560db99ac8dbc5c4e8cd5 Mon Sep 17 00:00:00 2001
+From e622295e18a1af30c999928701787d8c562621c3 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 28 Dec 2022 22:24:25 +0800
-Subject: [PATCH 23/39] wifi: mt76: testmode: add atenl support in mt7996
+Subject: [PATCH 35/98] wifi: mt76: testmode: add atenl support in mt7996
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
@@ -10,10 +10,10 @@
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/testmode.c b/testmode.c
-index 0accc71..0d2bae9 100644
+index 4644dac..5c93aa6 100644
--- a/testmode.c
+++ b/testmode.c
-@@ -612,7 +612,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -613,7 +613,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
if (dev->test_mtd.name &&
(nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-testmode-add-basic-testmode-support.patch
similarity index 83%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-testmode-add-basic-testmode-support.patch
index 6facdc3..5b78a59 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-testmode-add-basic-testmode-support.patch
@@ -1,36 +1,37 @@
-From 826ab7312fa42110844329a333df76dec614e48f Mon Sep 17 00:00:00 2001
+From ce58ffb18be834e2f62a30a71c9d6f5805517a9e Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 1 Mar 2023 11:59:16 +0800
-Subject: [PATCH] wifi: mt76: testmode: add basic testmode support
+Subject: [PATCH 36/98] wifi: mt76: testmode: add basic testmode support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
eeprom.c | 6 +-
mac80211.c | 3 +-
- mt76.h | 33 +++
+ mt76.h | 35 +++
mt76_connac_mcu.h | 2 +
- mt7996/Makefile | 2 +
+ mt7996/Makefile | 1 +
mt7996/eeprom.c | 35 ++-
mt7996/eeprom.h | 1 +
- mt7996/init.c | 7 +
+ mt7996/init.c | 8 +
+ mt7996/mac.c | 3 +-
mt7996/main.c | 16 ++
mt7996/mcu.c | 42 ++-
mt7996/mcu.h | 27 ++
- mt7996/mt7996.h | 22 ++
- mt7996/testmode.c | 658 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/testmode.h | 295 +++++++++++++++++++++
- testmode.c | 73 +++--
- testmode.h | 60 +++++
- tools/fields.c | 92 +++++++
- 17 files changed, 1344 insertions(+), 30 deletions(-)
+ mt7996/mt7996.h | 23 ++
+ mt7996/testmode.c | 674 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/testmode.h | 297 ++++++++++++++++++++
+ testmode.c | 78 ++++--
+ testmode.h | 64 +++++
+ tools/fields.c | 102 ++++++-
+ 18 files changed, 1383 insertions(+), 34 deletions(-)
create mode 100644 mt7996/testmode.c
create mode 100644 mt7996/testmode.h
diff --git a/eeprom.c b/eeprom.c
-index ea54b7a..263e508 100644
+index a07ca84..437d8ca 100644
--- a/eeprom.c
+++ b/eeprom.c
-@@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
+@@ -94,8 +94,10 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs
}
#ifdef CONFIG_NL80211_TESTMODE
@@ -44,10 +45,10 @@
out_put_node:
diff --git a/mac80211.c b/mac80211.c
-index 467afef..d1cdaee 100644
+index cd102dd..f10ca90 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -826,7 +826,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
+@@ -835,7 +835,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
}
#ifdef CONFIG_NL80211_TESTMODE
@@ -58,10 +59,10 @@
if (status->flag & RX_FLAG_FAILED_FCS_CRC)
phy->test.rx_stats.fcs_error[q]++;
diff --git a/mt76.h b/mt76.h
-index 6b07b8f..31d5dc3 100644
+index 7f93210..feb861c 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -652,8 +652,12 @@ struct mt76_testmode_ops {
+@@ -692,14 +692,20 @@ struct mt76_testmode_ops {
int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
enum mt76_testmode_state new_state);
int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
@@ -74,7 +75,15 @@
struct mt76_testmode_data {
enum mt76_testmode_state state;
-@@ -669,6 +673,7 @@ struct mt76_testmode_data {
+ u32 param_set[DIV_ROUND_UP(NUM_MT76_TM_ATTRS, 32)];
+ struct sk_buff *tx_skb;
+
++ u8 sku_en;
++
+ u32 tx_count;
+ u16 tx_mpdu_len;
+
+@@ -709,6 +715,7 @@ struct mt76_testmode_data {
u8 tx_rate_sgi;
u8 tx_rate_ldpc;
u8 tx_rate_stbc;
@@ -82,7 +91,7 @@
u8 tx_ltf;
u8 tx_antenna_mask;
-@@ -678,6 +683,9 @@ struct mt76_testmode_data {
+@@ -718,6 +725,9 @@ struct mt76_testmode_data {
u32 tx_time;
u32 tx_ipg;
@@ -92,7 +101,7 @@
u32 freq_offset;
u8 tx_power[4];
-@@ -692,7 +700,16 @@ struct mt76_testmode_data {
+@@ -732,7 +742,16 @@ struct mt76_testmode_data {
struct {
u64 packets[__MT_RXQ_MAX];
u64 fcs_error[__MT_RXQ_MAX];
@@ -109,7 +118,7 @@
};
struct mt76_vif {
-@@ -1258,6 +1275,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1418,6 +1437,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
@@ -133,10 +142,10 @@
{
#ifdef CONFIG_NL80211_TESTMODE
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 30c9a5d..724a48a 100644
+index ca2e573..4d054bd 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1218,10 +1218,12 @@ enum {
+@@ -1239,12 +1239,14 @@ enum {
MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
MCU_UNI_CMD_RA = 0x2f,
MCU_UNI_CMD_MURU = 0x31,
@@ -145,22 +154,25 @@
MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
MCU_UNI_CMD_THERMAL = 0x35,
MCU_UNI_CMD_VOW = 0x37,
+ MCU_UNI_CMD_PP = 0x38,
+ MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
+ MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
- MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
+ MCU_UNI_CMD_PER_STA_INFO = 0x6d,
diff --git a/mt7996/Makefile b/mt7996/Makefile
-index 07c8b55..bed9efd 100644
+index a056b40..7bb17f4 100644
--- a/mt7996/Makefile
+++ b/mt7996/Makefile
-@@ -6,3 +6,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
+@@ -8,5 +8,6 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o
mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
-+
+mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
+
+ mt7996e-y += mtk_debugfs.o mtk_mcu.o
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 544b6c6..f5e9546 100644
+index 7ae92e1..7fd318c 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
@@ -6,6 +6,11 @@
@@ -230,7 +242,7 @@
if (ret < 0)
return ret;
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 0c74977..0f8f0cd 100644
+index 412d6e2..9ea3667 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
@@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
@@ -242,10 +254,10 @@
MT_EE_RATE_DELTA_2G = 0x1400,
MT_EE_RATE_DELTA_5G = 0x147d,
diff --git a/mt7996/init.c b/mt7996/init.c
-index 0319e7f..fecd0d3 100644
+index 273d1e7..6d39c3c 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -641,6 +641,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -800,6 +800,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
@@ -256,18 +268,33 @@
ret = mt7996_mcu_init(dev);
if (ret)
return ret;
-@@ -1056,6 +1060,9 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1217,6 +1221,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
- mt7996_init_wiphy(hw);
+ mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
+#ifdef CONFIG_NL80211_TESTMODE
+ dev->mt76.test_ops = &mt7996_testmode_ops;
+#endif
- /* init led callbacks */
- if (IS_ENABLED(CONFIG_MT76_LEDS)) {
- dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
++
+ ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+ ARRAY_SIZE(mt76_rates));
+ if (ret)
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 32c52fc..637f0f6 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -685,7 +685,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
+ *info);
+ }
+
+- if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
++ if (rxv && mode >= MT_PHY_TYPE_HE_SU && mode < MT_PHY_TYPE_EHT_SU &&
++ !(status->flag & RX_FLAG_8023))
+ mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
+
+ if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
diff --git a/mt7996/main.c b/mt7996/main.c
-index 8e38ebc..6c38993 100644
+index 0e51fe0..226235c 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -23,6 +23,18 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
@@ -298,7 +325,7 @@
mt7996_mac_enable_nf(dev, phy->mt76->band_idx);
ret = mt7996_mcu_set_rts_thresh(phy, 0x92b);
-@@ -1389,6 +1403,8 @@ const struct ieee80211_ops mt7996_ops = {
+@@ -1478,6 +1492,8 @@ const struct ieee80211_ops mt7996_ops = {
.sta_set_decap_offload = mt7996_sta_set_decap_offload,
.add_twt_setup = mt7996_mac_add_twt_setup,
.twt_teardown_request = mt7996_twt_teardown_request,
@@ -308,10 +335,10 @@
.sta_add_debugfs = mt7996_sta_add_debugfs,
#endif
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 665457a..0d2053c 100644
+index 7d0c511..141b838 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -2515,8 +2515,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+@@ -2681,8 +2681,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
{
int ret;
@@ -326,9 +353,9 @@
if (ret)
return ret;
-@@ -4066,3 +4070,37 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
- sizeof(req), true);
+@@ -4308,3 +4312,37 @@ int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, bool auto_mode,
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP),
+ &req, sizeof(req), false);
}
+
+int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
@@ -365,10 +392,10 @@
+ &req, sizeof(req), false);
+}
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index f235175..4ba06d9 100644
+index ca16336..16ffc3d 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -703,6 +703,33 @@ enum {
+@@ -814,6 +814,33 @@ enum {
UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
};
@@ -403,10 +430,10 @@
UNI_CMD_ACCESS_REG_BASIC = 0x0,
UNI_CMD_ACCESS_RF_REG_BASIC,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 071031b..f7d6580 100644
+index 8801956..3964035 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -31,9 +31,11 @@
+@@ -32,9 +32,11 @@
#define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
#define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
@@ -418,18 +445,18 @@
#define MT7996_EEPROM_SIZE 7680
#define MT7996_EEPROM_BLOCK_SIZE 16
#define MT7996_TOKEN_SIZE 16384
-@@ -63,6 +65,7 @@ struct mt7996_dfs_pattern;
+@@ -83,6 +85,7 @@ struct mt7996_dfs_pattern;
enum mt7996_ram_type {
MT7996_RAM_TYPE_WM,
+ MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
MT7996_RAM_TYPE_WA,
MT7996_RAM_TYPE_DSP,
- };
-@@ -244,6 +247,20 @@ struct mt7996_phy {
-
- struct mib_stats mib;
+ __MT7996_RAM_TYPE_MAX,
+@@ -225,6 +228,21 @@ struct mt7996_phy {
struct mt76_channel_state state_ts;
+
+ bool has_aux_rx;
+
+#ifdef CONFIG_NL80211_TESTMODE
+ struct {
@@ -437,6 +464,7 @@
+
+ s32 last_freq_offset;
+ u8 last_rcpi[4];
++ s8 last_rssi[4];
+ s8 last_ib_rssi[4];
+ s8 last_wb_rssi[4];
+ u8 last_snr;
@@ -447,16 +475,16 @@
};
struct mt7996_dev {
-@@ -303,6 +320,8 @@ struct mt7996_dev {
- bool flash_mode:1;
- bool has_eht:1;
+@@ -300,6 +318,8 @@ struct mt7996_dev {
+ } session;
+ } wed_rro;
+ bool testmode_enable;
+
bool ibf;
u8 fw_debug_wm;
u8 fw_debug_wa;
-@@ -408,6 +427,7 @@ mt7996_phy3(struct mt7996_dev *dev)
+@@ -414,6 +434,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
extern const struct ieee80211_ops mt7996_ops;
extern struct pci_driver mt7996_pci_driver;
extern struct pci_driver mt7996_hif_driver;
@@ -464,7 +492,7 @@
struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id);
-@@ -417,6 +437,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+@@ -423,6 +444,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
int mt7996_register_device(struct mt7996_dev *dev);
void mt7996_unregister_device(struct mt7996_dev *dev);
int mt7996_eeprom_init(struct mt7996_dev *dev);
@@ -472,20 +500,20 @@
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
struct ieee80211_channel *chan);
-@@ -494,6 +515,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
- int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+@@ -508,6 +530,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
diff --git a/mt7996/testmode.c b/mt7996/testmode.c
new file mode 100644
-index 0000000..43eca4e
+index 0000000..fb041c3
--- /dev/null
+++ b/mt7996/testmode.c
-@@ -0,0 +1,658 @@
+@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2022 MediaTek Inc.
@@ -499,6 +527,7 @@
+enum {
+ TM_CHANGED_TXPOWER,
+ TM_CHANGED_FREQ_OFFSET,
++ TM_CHANGED_SKU_EN,
+ TM_CHANGED_TX_LENGTH,
+ TM_CHANGED_TX_TIME,
+ TM_CHANGED_CFG,
@@ -510,6 +539,7 @@
+static const u8 tm_change_map[] = {
+ [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
+ [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
++ [TM_CHANGED_SKU_EN] = MT76_TM_ATTR_SKU_EN,
+ [TM_CHANGED_TX_LENGTH] = MT76_TM_ATTR_TX_LENGTH,
+ [TM_CHANGED_TX_TIME] = MT76_TM_ATTR_TX_TIME,
+ [TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
@@ -681,7 +711,6 @@
+static void
+mt7996_tm_init(struct mt7996_phy *phy, bool en)
+{
-+#define POWER_CTRL(type) UNI_TXPOWER_##type##_CTRL
+ struct mt7996_dev *dev = phy->dev;
+ u8 rf_test_mode = en ? RF_OPER_RF_TEST : RF_OPER_NORMAL;
+
@@ -690,8 +719,6 @@
+
+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(ATE_MODE), en);
+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(SKU_POWER_LIMIT), !en);
-+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(PERCENTAGE_DROP), 100);
-+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(PERCENTAGE), !en);
+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(BACKOFF_POWER_LIMIT), !en);
+
+ mt7996_tm_rf_switch_mode(dev, rf_test_mode);
@@ -896,6 +923,12 @@
+ mt7996_tm_set(dev, SET_ID(FREQ_OFFSET), en ? td->freq_offset : 0);
+ if (changed & BIT(TM_CHANGED_TXPOWER))
+ mt7996_tm_set(dev, SET_ID(POWER), td->tx_power[0]);
++ if (changed & BIT(TM_CHANGED_SKU_EN)) {
++ mt7996_tm_update_channel(phy);
++ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(SKU_POWER_LIMIT), td->sku_en);
++ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(BACKOFF_POWER_LIMIT), td->sku_en);
++ mt7996_mcu_set_txpower_sku(phy);
++ }
+ if (changed & BIT(TM_CHANGED_TX_LENGTH)) {
+ mt7996_tm_set(dev, SET_ID(TX_LEN), td->tx_mpdu_len);
+ mt7996_tm_set(dev, SET_ID(TX_TIME), 0);
@@ -1028,6 +1061,7 @@
+ phy->test.last_snr = le32_to_cpu(rx_stats_all->user_info[0].snr);
+ for (i = 0; i < ARRAY_SIZE(phy->test.last_rcpi); i++) {
+ phy->test.last_rcpi[i] = le16_to_cpu(rx_stats_all->rxv_info[i].rcpi);
++ phy->test.last_rssi[i] = le16_to_cpu(rx_stats_all->rxv_info[i].rssi);
+ phy->test.last_ib_rssi[i] = rx_stats_all->fagc[i].ib_rssi;
+ phy->test.last_wb_rssi[i] = rx_stats_all->fagc[i].wb_rssi;
+ }
@@ -1109,6 +1143,16 @@
+
+ nla_nest_end(msg, rssi);
+
++ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RSSI);
++ if (!rssi)
++ return -ENOMEM;
++
++ for (i = 0; i < ARRAY_SIZE(phy->test.last_rssi); i++)
++ if (nla_put_s8(msg, i, phy->test.last_rssi[i]))
++ return -ENOMEM;
++
++ nla_nest_end(msg, rssi);
++
+ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI);
+ if (!rssi)
+ return -ENOMEM;
@@ -1146,10 +1190,10 @@
+};
diff --git a/mt7996/testmode.h b/mt7996/testmode.h
new file mode 100644
-index 0000000..f00e51f
+index 0000000..e4d55a6
--- /dev/null
+++ b/mt7996/testmode.h
-@@ -0,0 +1,295 @@
+@@ -0,0 +1,297 @@
+/* SPDX-License-Identifier: ISC */
+/* Copyright (C) 2020 MediaTek Inc. */
+
@@ -1307,6 +1351,8 @@
+ RF_TEST_ID_SET_AID_OFFSET = 204,
+};
+
++#define POWER_CTRL(type) UNI_TXPOWER_##type##_CTRL
++
+struct mt7996_tm_rx_stat_user_ctrl {
+ __le16 tag;
+ __le16 len;
@@ -1446,10 +1492,10 @@
+
+#endif
diff --git a/testmode.c b/testmode.c
-index 0d2bae9..fc68c2a 100644
+index 5c93aa6..bbe8230 100644
--- a/testmode.c
+++ b/testmode.c
-@@ -2,6 +2,7 @@
+@@ -2,11 +2,13 @@
/* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
#include <linux/random.h>
@@ -1457,7 +1503,13 @@
#include "mt76.h"
const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
-@@ -81,6 +82,11 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
+ [MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
+ [MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
++ [MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
+ [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
+@@ -82,6 +84,11 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991)
return IEEE80211_MAX_MPDU_LEN_VHT_7991;
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
@@ -1469,7 +1521,7 @@
case MT76_TM_TX_MODE_CCK:
case MT76_TM_TX_MODE_OFDM:
default:
-@@ -182,6 +188,9 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -183,6 +190,9 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
u8 max_nss = hweight8(phy->antenna_mask);
int ret;
@@ -1479,7 +1531,7 @@
ret = mt76_testmode_alloc_skb(phy, td->tx_mpdu_len);
if (ret)
return ret;
-@@ -274,7 +283,9 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
+@@ -275,7 +285,9 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
td->tx_queued = 0;
td->tx_done = 0;
td->tx_pending = td->tx_count;
@@ -1490,7 +1542,7 @@
}
static void
-@@ -283,6 +294,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
+@@ -284,6 +296,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
@@ -1502,7 +1554,7 @@
mt76_worker_disable(&dev->tx_worker);
td->tx_pending = 0;
-@@ -295,22 +311,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
+@@ -296,22 +313,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
mt76_testmode_free_skb(phy);
}
@@ -1526,7 +1578,7 @@
if (td->tx_mpdu_len > 0)
return;
-@@ -318,11 +323,18 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
+@@ -319,11 +325,18 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
td->tx_mpdu_len = 1024;
td->tx_count = 1;
td->tx_rate_mode = MT76_TM_TX_MODE_OFDM;
@@ -1535,20 +1587,20 @@
+ /* 0xffff for OFDMA no puncture */
+ td->tx_preamble_puncture = ~(td->tx_preamble_puncture & 0);
+ td->tx_ipg = 50;
-+
-+ /* rx stat user config */
-+ td->aid = 1;
- memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
- memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
- memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
++ /* rx stat user config */
++ td->aid = 1;
++
+ memcpy(td->addr[0], addr, ETH_ALEN);
+ memcpy(td->addr[1], addr, ETH_ALEN);
+ memcpy(td->addr[2], addr, ETH_ALEN);
}
static int
-@@ -352,7 +364,7 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
+@@ -353,7 +366,7 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
if (state == MT76_TM_STATE_TX_FRAMES)
mt76_testmode_tx_start(phy);
else if (state == MT76_TM_STATE_RX_FRAMES) {
@@ -1557,7 +1609,17 @@
}
phy->test.state = state;
-@@ -453,7 +465,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -434,6 +447,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+
+ mt76_testmode_init_defaults(phy);
+
++ if (tb[MT76_TM_ATTR_SKU_EN])
++ td->sku_en = nla_get_u8(tb[MT76_TM_ATTR_SKU_EN]);
++
+ if (tb[MT76_TM_ATTR_TX_COUNT])
+ td->tx_count = nla_get_u32(tb[MT76_TM_ATTR_TX_COUNT]);
+
+@@ -454,7 +470,8 @@ 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],
@@ -1567,7 +1629,7 @@
goto out;
if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -493,7 +506,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -494,7 +511,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
idx >= ARRAY_SIZE(td->tx_power))
goto out;
@@ -1578,7 +1640,7 @@
}
}
-@@ -511,6 +526,22 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -512,6 +531,22 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
}
@@ -1601,7 +1663,7 @@
if (dev->test_ops->set_params) {
err = dev->test_ops->set_params(phy, tb, state);
if (err)
-@@ -560,6 +591,9 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
+@@ -561,6 +596,9 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_PACKETS, rx_packets,
MT76_TM_STATS_ATTR_PAD) ||
nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_FCS_ERROR, rx_fcs_error,
@@ -1611,19 +1673,28 @@
MT76_TM_STATS_ATTR_PAD))
return -EMSGSIZE;
-@@ -624,6 +658,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -625,6 +663,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) ||
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
++ nla_put_u8(msg, MT76_TM_ATTR_SKU_EN, td->sku_en) ||
+ nla_put_u8(msg, MT76_TM_ATTR_AID, td->aid) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
diff --git a/testmode.h b/testmode.h
-index a40cd74..8d0b970 100644
+index a40cd74..141bb86 100644
--- a/testmode.h
+++ b/testmode.h
-@@ -39,6 +39,11 @@
+@@ -19,6 +19,7 @@
+ * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
+ * @MT76_TM_ATTR_BAND_IDX: band idx of the chip (u8)
+ *
++ * @MT76_TM_ATTR_SKU_EN: config txpower sku is enabled or disabled in testmode (u8)
+ * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
+ * state to MT76_TM_STATE_TX_FRAMES (u32)
+ * @MT76_TM_ATTR_TX_PENDING: pending frames during MT76_TM_STATE_TX_FRAMES (u32)
+@@ -39,6 +40,11 @@
*
* @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
*
@@ -1635,7 +1706,7 @@
* @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
*
* @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
-@@ -48,6 +53,29 @@
+@@ -48,6 +54,29 @@
* @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
*
* @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
@@ -1665,7 +1736,15 @@
*/
enum mt76_testmode_attr {
MT76_TM_ATTR_UNSPEC,
-@@ -76,6 +104,8 @@ enum mt76_testmode_attr {
+@@ -59,6 +88,7 @@ enum mt76_testmode_attr {
+ MT76_TM_ATTR_MTD_OFFSET,
+ MT76_TM_ATTR_BAND_IDX,
+
++ MT76_TM_ATTR_SKU_EN,
+ MT76_TM_ATTR_TX_COUNT,
+ MT76_TM_ATTR_TX_LENGTH,
+ MT76_TM_ATTR_TX_RATE_MODE,
+@@ -76,6 +106,8 @@ enum mt76_testmode_attr {
MT76_TM_ATTR_FREQ_OFFSET,
MT76_TM_ATTR_STATS,
@@ -1674,7 +1753,7 @@
MT76_TM_ATTR_TX_SPE_IDX,
-@@ -86,6 +116,27 @@ enum mt76_testmode_attr {
+@@ -86,6 +118,27 @@ enum mt76_testmode_attr {
MT76_TM_ATTR_DRV_DATA,
MT76_TM_ATTR_MAC_ADDRS,
@@ -1702,7 +1781,7 @@
/* keep last */
NUM_MT76_TM_ATTRS,
-@@ -103,6 +154,8 @@ enum mt76_testmode_attr {
+@@ -103,6 +156,8 @@ enum mt76_testmode_attr {
* @MT76_TM_STATS_ATTR_RX_FCS_ERROR: number of rx packets with FCS error (u64)
* @MT76_TM_STATS_ATTR_LAST_RX: information about the last received packet
* see &enum mt76_testmode_rx_attr
@@ -1711,7 +1790,7 @@
*/
enum mt76_testmode_stats_attr {
MT76_TM_STATS_ATTR_UNSPEC,
-@@ -115,6 +168,7 @@ enum mt76_testmode_stats_attr {
+@@ -115,6 +170,7 @@ enum mt76_testmode_stats_attr {
MT76_TM_STATS_ATTR_RX_PACKETS,
MT76_TM_STATS_ATTR_RX_FCS_ERROR,
MT76_TM_STATS_ATTR_LAST_RX,
@@ -1719,7 +1798,23 @@
/* keep last */
NUM_MT76_TM_STATS_ATTRS,
-@@ -179,6 +233,9 @@ enum mt76_testmode_state {
+@@ -127,6 +183,7 @@ enum mt76_testmode_stats_attr {
+ *
+ * @MT76_TM_RX_ATTR_FREQ_OFFSET: frequency offset (s32)
+ * @MT76_TM_RX_ATTR_RCPI: received channel power indicator (array, u8)
++ * @MT76_TM_RX_ATTR_RSSI: received signal strength indicator (array, s8)
+ * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (array, s8)
+ * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (array, s8)
+ * @MT76_TM_RX_ATTR_SNR: signal-to-noise ratio (u8)
+@@ -136,6 +193,7 @@ enum mt76_testmode_rx_attr {
+
+ MT76_TM_RX_ATTR_FREQ_OFFSET,
+ MT76_TM_RX_ATTR_RCPI,
++ MT76_TM_RX_ATTR_RSSI,
+ MT76_TM_RX_ATTR_IB_RSSI,
+ MT76_TM_RX_ATTR_WB_RSSI,
+ MT76_TM_RX_ATTR_SNR,
+@@ -179,6 +237,9 @@ enum mt76_testmode_state {
* @MT76_TM_TX_MODE_HE_EXT_SU: 802.11ax extended-range SU
* @MT76_TM_TX_MODE_HE_TB: 802.11ax trigger-based
* @MT76_TM_TX_MODE_HE_MU: 802.11ax multi-user MIMO
@@ -1729,7 +1824,7 @@
*/
enum mt76_testmode_tx_mode {
MT76_TM_TX_MODE_CCK,
-@@ -189,6 +246,9 @@ enum mt76_testmode_tx_mode {
+@@ -189,6 +250,9 @@ enum mt76_testmode_tx_mode {
MT76_TM_TX_MODE_HE_EXT_SU,
MT76_TM_TX_MODE_HE_TB,
MT76_TM_TX_MODE_HE_MU,
@@ -1740,7 +1835,7 @@
/* keep last */
NUM_MT76_TM_TX_MODES,
diff --git a/tools/fields.c b/tools/fields.c
-index e3f6908..e5cf7c5 100644
+index e3f6908..055f90f 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -1761,6 +1856,30 @@
};
static void print_enum(const struct tm_field *field, struct nlattr *attr)
+@@ -65,7 +69,7 @@ static bool parse_u8(const struct tm_field *field, int idx,
+
+ static void print_u8(const struct tm_field *field, struct nlattr *attr)
+ {
+- printf("%d", nla_get_u8(attr));
++ printf("%u", nla_get_u8(attr));
+ }
+
+ static void print_s8(const struct tm_field *field, struct nlattr *attr)
+@@ -86,12 +90,12 @@ static void print_s32(const struct tm_field *field, struct nlattr *attr)
+
+ static void print_u32(const struct tm_field *field, struct nlattr *attr)
+ {
+- printf("%d", nla_get_u32(attr));
++ printf("%u", nla_get_u32(attr));
+ }
+
+ static void print_u64(const struct tm_field *field, struct nlattr *attr)
+ {
+- printf("%lld", (unsigned long long)nla_get_u64(attr));
++ printf("%llu", (unsigned long long)nla_get_u64(attr));
+ }
+
+ static bool parse_flag(const struct tm_field *field, int idx,
@@ -201,6 +205,62 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
printf("%srx_per=%.02f%%\n", prefix, 100 * failed / total);
}
@@ -1824,7 +1943,7 @@
#define FIELD_GENERIC(_field, _name, ...) \
[FIELD_NAME(_field)] = { \
-@@ -250,6 +310,13 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
+@@ -250,10 +310,18 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
##__VA_ARGS__ \
)
@@ -1838,7 +1957,20 @@
#define FIELD_NAME(_field) MT76_TM_RX_ATTR_##_field
static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
FIELD_RO(s32, FREQ_OFFSET, "freq_offset"),
-@@ -274,6 +341,7 @@ static const struct tm_field stats_fields[NUM_MT76_TM_STATS_ATTRS] = {
+ FIELD_ARRAY_RO(u8, RCPI, "rcpi"),
++ FIELD_ARRAY_RO(s8, RSSI, "rssi"),
+ FIELD_ARRAY_RO(s8, IB_RSSI, "ib_rssi"),
+ FIELD_ARRAY_RO(s8, WB_RSSI, "wb_rssi"),
+ FIELD_RO(s8, SNR, "snr"),
+@@ -261,6 +329,7 @@ static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
+ static struct nla_policy rx_policy[NUM_MT76_TM_RX_ATTRS] = {
+ [MT76_TM_RX_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
+ [MT76_TM_RX_ATTR_RCPI] = { .type = NLA_NESTED },
++ [MT76_TM_RX_ATTR_RSSI] = { .type = NLA_NESTED },
+ [MT76_TM_RX_ATTR_IB_RSSI] = { .type = NLA_NESTED },
+ [MT76_TM_RX_ATTR_WB_RSSI] = { .type = NLA_NESTED },
+ [MT76_TM_RX_ATTR_SNR] = { .type = NLA_U8 },
+@@ -274,6 +343,7 @@ static const struct tm_field stats_fields[NUM_MT76_TM_STATS_ATTRS] = {
FIELD_RO(u32, TX_DONE, "tx_done"),
FIELD_RO(u64, RX_PACKETS, "rx_packets"),
FIELD_RO(u64, RX_FCS_ERROR, "rx_fcs_error"),
@@ -1846,7 +1978,7 @@
FIELD_NESTED_RO(LAST_RX, rx, "last_"),
};
static struct nla_policy stats_policy[NUM_MT76_TM_STATS_ATTRS] = {
-@@ -282,6 +350,7 @@ static struct nla_policy stats_policy[NUM_MT76_TM_STATS_ATTRS] = {
+@@ -282,6 +352,7 @@ static struct nla_policy stats_policy[NUM_MT76_TM_STATS_ATTRS] = {
[MT76_TM_STATS_ATTR_TX_DONE] = { .type = NLA_U32 },
[MT76_TM_STATS_ATTR_RX_PACKETS] = { .type = NLA_U64 },
[MT76_TM_STATS_ATTR_RX_FCS_ERROR] = { .type = NLA_U64 },
@@ -1854,7 +1986,15 @@
};
#undef FIELD_NAME
-@@ -300,12 +369,20 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+@@ -291,6 +362,7 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+ FIELD_ENUM(STATE, "state", testmode_state),
+ FIELD_RO(string, MTD_PART, "mtd_part"),
+ FIELD_RO(u32, MTD_OFFSET, "mtd_offset"),
++ FIELD(u8, SKU_EN, "sku_en"),
+ FIELD(u32, TX_COUNT, "tx_count"),
+ FIELD(u32, TX_LENGTH, "tx_length"),
+ FIELD_ENUM(TX_RATE_MODE, "tx_rate_mode", testmode_tx_mode),
+@@ -300,12 +372,20 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
FIELD(u8, TX_RATE_LDPC, "tx_rate_ldpc"),
FIELD(u8, TX_RATE_STBC, "tx_rate_stbc"),
FIELD(u8, TX_LTF, "tx_ltf"),
@@ -1875,7 +2015,15 @@
};
#undef FIELD_NAME
-@@ -322,10 +399,25 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
+@@ -313,6 +393,7 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
+ [MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
+ [MT76_TM_ATTR_MTD_PART] = { .type = NLA_STRING },
+ [MT76_TM_ATTR_MTD_OFFSET] = { .type = NLA_U32 },
++ [MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
+ [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
+@@ -322,10 +403,25 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch
new file mode 100644
index 0000000..dbef00c
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch
@@ -0,0 +1,111 @@
+From 10df4848e7a7116529e1f596e06d0d03891f502e Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 20 Jul 2023 17:27:22 +0800
+Subject: [PATCH 37/98] wifi: mt76: mt7996: add eagle default bin of different
+ sku variants
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 2 ++
+ mt7996/init.c | 4 ++++
+ mt7996/mt7996.h | 28 ++++++++++++++++++++++++++--
+ 3 files changed, 32 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 7fd318c..3276740 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -30,6 +30,8 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ /* reserve for future variants */
+ if (dev->testmode_enable)
+ return MT7996_EEPROM_DEFAULT_TM;
++ else if (dev->chip_sku == MT7996_SKU_404)
++ return MT7996_EEPROM_DEFAULT_404;
+ else
+ return MT7996_EEPROM_DEFAULT;
+ }
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 6d39c3c..fed74d0 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -789,6 +789,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+
+ INIT_WORK(&dev->init_work, mt7996_init_work);
+
++ ret = mt7996_get_chip_sku(dev);
++ if (ret)
++ return ret;
++
+ dev->dbdc_support = mt7996_band_valid(dev, MT_BAND1) ||
+ mt7996_band_valid(dev, MT_BAND2);
+ dev->tbtc_support = mt7996_band_valid(dev, MT_BAND1) &&
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 3964035..efdcff7 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -36,6 +36,7 @@
+ #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
+
+ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
++#define MT7996_EEPROM_DEFAULT_404 "mediatek/mt7996/mt7996_eeprom_dual_404.bin"
+ #define MT7996_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7996_eeprom_tm.bin"
+ #define MT7996_EEPROM_SIZE 7680
+ #define MT7996_EEPROM_BLOCK_SIZE 16
+@@ -83,6 +84,11 @@ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+ struct mt7996_dfs_pattern;
+
++enum mt7996_sku_type {
++ MT7996_SKU_404,
++ MT7996_SKU_444,
++};
++
+ enum mt7996_ram_type {
+ MT7996_RAM_TYPE_WM,
+ MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
+@@ -264,6 +270,8 @@ struct mt7996_dev {
+ struct cfg80211_chan_def rdd2_chandef;
+ struct mt7996_phy *rdd2_phy;
+
++ u8 chip_sku;
++
+ u16 chainmask;
+ u8 chainshift[__MT_MAX_BAND];
+ u32 hif_idx;
+@@ -417,6 +425,23 @@ mt7996_phy3(struct mt7996_dev *dev)
+ return __mt7996_phy(dev, MT_BAND2);
+ }
+
++static inline int
++mt7996_get_chip_sku(struct mt7996_dev *dev)
++{
++ u32 val = mt76_rr(dev, MT_PAD_GPIO);
++
++ /* reserve for future variants */
++ switch (mt76_chip(&dev->mt76)) {
++ case 0x7990:
++ dev->chip_sku = FIELD_GET(MT_PAD_GPIO_ADIE_COMB, val) <= 1;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static inline bool
+ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
+ {
+@@ -424,8 +449,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
+ return band <= MT_BAND1;
+
+ /* tri-band support */
+- if (band <= MT_BAND2 &&
+- mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
++ if (band <= MT_BAND2 && dev->chip_sku)
+ return true;
+
+ return band == MT_BAND0 || band == MT_BAND2;
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch
deleted file mode 100644
index 8eaf2d5..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 09b50cf201ede70688619366c31aa2ddd57d5cb2 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Fri, 31 Mar 2023 11:26:27 +0800
-Subject: [PATCH 1005/1015] wifi: mt76: mt7996: add U-NII-4 support
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- mac80211.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mac80211.c b/mac80211.c
-index d1cdaee8..501325e9 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -76,6 +76,7 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
- CHAN5G(165, 5825),
- CHAN5G(169, 5845),
- CHAN5G(173, 5865),
-+ CHAN5G(177, 5885),
- };
-
- static const struct ieee80211_channel mt76_channels_6ghz[] = {
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
similarity index 85%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
index c0ce85d..78ae8ad 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
@@ -1,7 +1,7 @@
-From 18f990de206c3301d3ae72cfeef40dfb3b361fb0 Mon Sep 17 00:00:00 2001
+From b02a81b168e9c42350c1f6a9b7e38c60c76cc692 Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Mon, 8 May 2023 09:03:50 +0800
-Subject: [PATCH 36/39] wifi: mt76: mt7996: enable SCS feature for mt7996
+Subject: [PATCH 38/98] wifi: mt76: mt7996: enable SCS feature for mt7996
driver
Enable Smart Carrier Sense algorithn by default to improve performance
@@ -14,35 +14,35 @@
mt7996/main.c | 7 +++
mt7996/mcu.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.h | 6 +++
- mt7996/mt7996.h | 16 ++++++
- 6 files changed, 154 insertions(+)
+ mt7996/mt7996.h | 15 ++++++
+ 6 files changed, 153 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 97f874b..bfec420 100644
+index 4d054bd..fae76c9 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1213,6 +1213,7 @@ enum {
- MCU_UNI_CMD_GET_MIB_INFO = 0x22,
+@@ -1232,6 +1232,7 @@ enum {
+ MCU_UNI_CMD_GET_STAT_INFO = 0x23,
MCU_UNI_CMD_SNIFFER = 0x24,
MCU_UNI_CMD_SR = 0x25,
+ MCU_UNI_CMD_SCS = 0x26,
MCU_UNI_CMD_ROC = 0x27,
+ MCU_UNI_CMD_SET_DBDC_PARMS = 0x28,
MCU_UNI_CMD_TXPOWER = 0x2b,
- MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
diff --git a/mt7996/init.c b/mt7996/init.c
-index 0825e0b..1072874 100644
+index fed74d0..f393e04 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -1058,6 +1058,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1211,6 +1211,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
dev->mt76.phy.priv = &dev->phy;
INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
+ INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll);
INIT_LIST_HEAD(&dev->sta_rc_list);
- INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
+
diff --git a/mt7996/main.c b/mt7996/main.c
-index 520f250..20b89a7 100644
+index 226235c..6fa4a65 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -73,11 +73,17 @@ int mt7996_run(struct ieee80211_hw *hw)
@@ -72,10 +72,10 @@
mutex_lock(&dev->mt76.mutex);
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 9fb800a..a5c473a 100644
+index 141b838..6cedc39 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -4190,3 +4190,126 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+@@ -4346,3 +4346,126 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TXPOWER),
&req, sizeof(req), false);
}
@@ -203,11 +203,11 @@
+ &req, sizeof(req), false);
+}
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index eed7371..eb63441 100644
+index 16ffc3d..ff9cc9c 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -757,6 +757,12 @@ enum {
- MT7996_SEC_MODE_MAX,
+@@ -875,6 +875,12 @@ enum {
+ UNI_CMD_PP_EN_CTRL,
};
+enum {
@@ -220,14 +220,13 @@
#define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8)
#define MT7996_PATCH_AES_KEY GENMASK(7, 0)
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 488f59c..f78f1fd 100644
+index efdcff7..eb48dbd 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -222,6 +222,17 @@ struct mt7996_hif {
+@@ -193,6 +193,16 @@ struct mt7996_hif {
int irq;
};
-+
+struct mt7996_scs_ctrl {
+ u8 scs_enable;
+ s8 sta_min_rssi;
@@ -238,10 +237,10 @@
+ SCS_ENABLE,
+};
+
- struct mt7996_phy {
- struct mt76_phy *mt76;
- struct mt7996_dev *dev;
-@@ -253,6 +264,8 @@ struct mt7996_phy {
+ struct mt7996_wed_rro_addr {
+ u32 head_low;
+ u32 head_high : 4;
+@@ -235,6 +245,8 @@ struct mt7996_phy {
bool has_aux_rx;
@@ -250,7 +249,7 @@
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
-@@ -295,6 +308,7 @@ struct mt7996_dev {
+@@ -280,6 +292,7 @@ struct mt7996_dev {
struct work_struct rc_work;
struct work_struct dump_work;
struct work_struct reset_work;
@@ -258,9 +257,9 @@
wait_queue_head_t reset_wait;
struct {
u32 state;
-@@ -535,6 +549,8 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
- void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+@@ -555,6 +568,8 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
+int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+void mt7996_mcu_scs_sta_poll(struct work_struct *work);
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch
similarity index 87%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch
index 75fa826..0a0d376 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch
@@ -1,7 +1,7 @@
-From b729a28ee5895d921e8df1a371e114dee7724595 Mon Sep 17 00:00:00 2001
+From 1c1dd57bde8919fdf04ef914b781eb6183582562 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 24 Mar 2023 23:35:30 +0800
-Subject: [PATCH 1001/1015] wifi: mt76: mt7996: add txpower support
+Subject: [PATCH 39/98] wifi: mt76: mt7996: add txpower support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Change-Id: Ic3e7b17f3664fa7f774137572f885359fa2ec93b
@@ -13,14 +13,14 @@
mt7996/mtk_debugfs.c | 229 +++++++++++++++++++++++++++++++++++++++++++
mt7996/mtk_mcu.c | 23 +++++
mt7996/mtk_mcu.h | 78 +++++++++++++++
- mt7996/regs.h | 17 +++-
- 8 files changed, 423 insertions(+), 5 deletions(-)
+ mt7996/regs.h | 29 +++---
+ 8 files changed, 429 insertions(+), 11 deletions(-)
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index b81ed64c..be0a34ae 100644
+index 3276740..e4c4b86 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
-@@ -293,3 +293,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
+@@ -296,3 +296,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
}
@@ -59,7 +59,7 @@
+ [SKU_EHT3x996_484] = 16,
+};
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 9ea3667f..343e65e1 100644
+index 9ea3667..343e65e 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
@@ -75,4 +75,46 @@ mt7996_get_channel_group_6g(int channel)
@@ -110,10 +110,10 @@
+
#endif
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 549007f9..5d52b0b7 100644
+index ff9cc9c..71dc165 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -712,6 +712,7 @@ struct tx_power_ctrl {
+@@ -826,6 +826,7 @@ struct tx_power_ctrl {
bool ate_mode_enable;
bool percentage_ctrl_enable;
bool bf_backoff_enable;
@@ -121,7 +121,7 @@
u8 power_drop_level;
};
u8 band_idx;
-@@ -725,6 +726,7 @@ enum {
+@@ -839,6 +840,7 @@ enum {
UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
UNI_TXPOWER_ATE_MODE_CTRL = 6,
@@ -130,31 +130,31 @@
enum {
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 6c76ec20..085307ab 100644
+index eb48dbd..23d1614 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -60,6 +60,8 @@
+@@ -63,6 +63,8 @@
#define MT7996_BUILD_TIME_LEN 24
+#define MT7996_SKU_RATE_NUM 417
+
- struct mt7996_vif;
- struct mt7996_sta;
- struct mt7996_dfs_pulse;
-@@ -563,6 +565,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
- void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #define MT7996_RRO_MAX_SESSION 1024
+ #define MT7996_RRO_WINDOW_MAX_LEN 1024
+ #define MT7996_RRO_ADDR_ELEM_LEN 128
+@@ -568,6 +570,7 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
void mt7996_mcu_scs_sta_poll(struct work_struct *work);
diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
-index f04c300f..2aee3ab0 100644
+index 5aa5c94..57fcbab 100644
--- a/mt7996/mtk_debugfs.c
+++ b/mt7996/mtk_debugfs.c
-@@ -2299,6 +2299,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
+@@ -2325,6 +2325,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
return 0;
}
@@ -387,7 +387,7 @@
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
{
struct mt7996_dev *dev = phy->dev;
-@@ -2341,6 +2567,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+@@ -2367,6 +2593,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir,
mt7996_trinfo_read);
@@ -398,7 +398,7 @@
debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
mt7996_wtbl_read);
diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
-index e8870166..f772243b 100644
+index e887016..f772243 100644
--- a/mt7996/mtk_mcu.c
+++ b/mt7996/mtk_mcu.c
@@ -12,7 +12,30 @@
@@ -433,7 +433,7 @@
#endif
diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
-index e741aa27..1fa449ea 100644
+index e741aa2..beb1aba 100644
--- a/mt7996/mtk_mcu.h
+++ b/mt7996/mtk_mcu.h
@@ -10,6 +10,84 @@
@@ -454,22 +454,22 @@
+
+ /* power percentage info */
+ bool percentage_ctrl_enable;
-+ u8 power_drop_level;
++ s8 power_drop_level;
+
+ /* frond-end loss TX info */
-+ u8 front_end_loss_tx[4];
++ s8 front_end_loss_tx[4];
+
+ /* frond-end loss RX info */
-+ u8 front_end_loss_rx[4];
++ s8 front_end_loss_rx[4];
+
+ /* thermal info */
+ bool thermal_compensate_enable;
-+ u8 thermal_compensate_value;
++ s8 thermal_compensate_value;
+ u8 rsv2;
+
+ /* TX power max/min limit info */
-+ u8 max_power_bound;
-+ u8 min_power_bound;
++ s8 max_power_bound;
++ s8 min_power_bound;
+
+ /* power limit info */
+ bool sku_enable;
@@ -477,8 +477,8 @@
+
+ /* MU TX power info */
+ bool mu_tx_power_manual_enable;
-+ u8 mu_tx_power_auto;
-+ u8 mu_tx_power_manual;
++ s8 mu_tx_power_auto;
++ s8 mu_tx_power_manual;
+ u8 rsv3;
+};
+
@@ -522,12 +522,12 @@
#endif
diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 3a5914c4..6ef905a9 100644
+index de5df91..565022a 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
-@@ -562,15 +562,22 @@ enum base_rev {
-
- #define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188)
+@@ -672,24 +672,31 @@ enum offs_rev {
+ ((_wf) << 16) + (ofs))
+ #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
-/* PHYRX CTRL */
-#define MT_WF_PHYRX_BAND_BASE 0x83080000
@@ -537,6 +537,19 @@
+#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \
((_band) << 20) + (ofs))
+-#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
+-#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
++#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHY_BAND(_band, 0x1054)
++#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHY_BAND(_band, 0x1058)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHY_BAND(_band, 0x105c)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHY_BAND(_band, 0x1060)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHY_BAND(_band, 0x1064)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHY_BAND(_band, 0x1068)
+
-#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
+/* PHYRX CTRL */
+#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHY_BAND(_band, 0x2004)
@@ -549,12 +562,6 @@
+#define MT_WF_PHY_TPC_POWER_RMAC GENMASK(23, 16)
+#define MT_WF_PHY_TPC_POWER_TSSI GENMASK(31, 24)
+
- /* PHYRX CSD */
- #define MT_WF_PHYRX_CSD_BASE 0x83000000
- #define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \
-@@ -579,7 +586,7 @@ enum base_rev {
- #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
-
/* PHYRX CSD BAND */
-#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230)
+#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHY_BAND(_band, 0x8230)
@@ -562,5 +569,5 @@
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
similarity index 85%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
index fe75034..38754fa 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
@@ -1,23 +1,23 @@
-From 55619fa44187b6ed841f94c2bedbc4779457e3f9 Mon Sep 17 00:00:00 2001
+From 6c7addb48070af33da842ede744264149f2a9110 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 13 Dec 2022 15:17:43 +0800
-Subject: [PATCH 1002/1015] wifi: mt76: mt7996: add mu vendor command support
+Subject: [PATCH 40/98] wifi: mt76: mt7996: add mu vendor command support
Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
---
mt7996/Makefile | 3 +-
mt7996/init.c | 8 +++++
- mt7996/mcu.c | 37 +++++++++++++++++++---
+ mt7996/mcu.c | 37 ++++++++++++++++++---
mt7996/mcu.h | 12 +++++++
- mt7996/mt7996.h | 7 +++++
- mt7996/vendor.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mt7996.h | 6 ++++
+ mt7996/vendor.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
mt7996/vendor.h | 22 +++++++++++++
7 files changed, 167 insertions(+), 6 deletions(-)
create mode 100644 mt7996/vendor.c
create mode 100644 mt7996/vendor.h
diff --git a/mt7996/Makefile b/mt7996/Makefile
-index df131869..8dbbc34c 100644
+index 7bb17f4..6643c7a 100644
--- a/mt7996/Makefile
+++ b/mt7996/Makefile
@@ -1,11 +1,12 @@
@@ -33,12 +33,12 @@
+ debugfs.o mmio.o vendor.o
mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
-
+ mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
diff --git a/mt7996/init.c b/mt7996/init.c
-index 96c4bb01..1d4359f0 100644
+index f393e04..1f4e84d 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -579,6 +579,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+@@ -597,6 +597,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
if (ret)
goto error;
@@ -49,7 +49,7 @@
ret = mt76_register_phy(mphy, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
-@@ -1082,6 +1086,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1230,6 +1234,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
dev->mt76.test_ops = &mt7996_testmode_ops;
#endif
@@ -61,10 +61,10 @@
ARRAY_SIZE(mt76_rates));
if (ret)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 58893348..91f3103a 100644
+index 6cedc39..a008c08 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -1158,6 +1158,8 @@ static void
+@@ -1266,6 +1266,8 @@ static void
mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
@@ -73,7 +73,7 @@
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
-@@ -1169,11 +1171,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1277,11 +1279,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
muru = (struct sta_rec_muru *)tlv;
@@ -93,7 +93,7 @@
if (sta->deflink.vht_cap.vht_supported)
muru->mimo_dl.vht_mu_bfee =
-@@ -4353,3 +4358,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+@@ -4469,3 +4474,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
&req, sizeof(req), false);
}
@@ -120,10 +120,10 @@
+}
+#endif
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 5d52b0b7..baffbcd7 100644
+index 71dc165..c5c0a44 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -568,8 +568,20 @@ enum {
+@@ -683,8 +683,20 @@ enum {
RATE_PARAM_FIXED_MCS,
RATE_PARAM_FIXED_GI = 11,
RATE_PARAM_AUTO = 20,
@@ -145,21 +145,20 @@
BF_SOUNDING_ON = 1,
BF_HW_EN_UPDATE = 17,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 085307ab..b9f3dd8e 100644
+index 23d1614..013122f 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -263,6 +263,8 @@ struct mt7996_phy {
- u32 rx_ampdu_ts;
- u32 ampdu_ref;
+@@ -249,6 +249,7 @@ struct mt7996_phy {
-+ u8 muru_onoff;
-+
- struct mib_stats mib;
- struct mt76_channel_state state_ts;
+ struct mt7996_scs_ctrl scs_ctrl;
-@@ -672,6 +674,11 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct dentry *dir);
- #endif
++ u8 muru_onoff;
+ #ifdef CONFIG_NL80211_TESTMODE
+ struct {
+ u32 *reg_backup;
+@@ -683,6 +684,11 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ bool hif2, int *irq);
+ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+#ifdef CONFIG_MTK_VENDOR
+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
@@ -171,10 +170,10 @@
#endif
diff --git a/mt7996/vendor.c b/mt7996/vendor.c
new file mode 100644
-index 00000000..08ecc2b3
+index 0000000..b5ecbdf
--- /dev/null
+++ b/mt7996/vendor.c
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
@@ -185,6 +184,7 @@
+#include "mt7996.h"
+#include "mcu.h"
+#include "vendor.h"
++#include "mtk_mcu.h"
+
+static const struct nla_policy
+mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
@@ -261,7 +261,7 @@
+}
diff --git a/mt7996/vendor.h b/mt7996/vendor.h
new file mode 100644
-index 00000000..8ac3ba8e
+index 0000000..8ac3ba8
--- /dev/null
+++ b/mt7996/vendor.h
@@ -0,0 +1,22 @@
@@ -288,5 +288,5 @@
+
+#endif
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch
index d83c3f9..45f1585 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch
@@ -1,7 +1,7 @@
-From 2637da59e92d101889cf3680e57f0594c6b349ec Mon Sep 17 00:00:00 2001
+From 98127145e2f401f65029185adab6dfcb0e90dbd9 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Wed, 26 Apr 2023 04:40:05 +0800
-Subject: [PATCH 1003/1015] wifi: mt76: mt7996: Add air monitor support
+Subject: [PATCH 41/98] wifi: mt76: mt7996: Add air monitor support
---
mt76_connac_mcu.h | 1 +
@@ -13,10 +13,10 @@
6 files changed, 445 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 4bb9508a..e62f17ad 100644
+index fae76c9..bbf600b 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1206,6 +1206,7 @@ enum {
+@@ -1222,6 +1222,7 @@ enum {
MCU_UNI_CMD_REG_ACCESS = 0x0d,
MCU_UNI_CMD_CHIP_CONFIG = 0x0e,
MCU_UNI_CMD_POWER_CTRL = 0x0f,
@@ -25,10 +25,10 @@
MCU_UNI_CMD_SER = 0x13,
MCU_UNI_CMD_TWT = 0x14,
diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 05269e7f..3dc5cdae 100644
+index 637f0f6..ee17d59 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -865,6 +865,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -679,6 +679,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
if (ieee80211_has_a4(fc) && is_mesh && status->amsdu)
*qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
}
@@ -38,12 +38,12 @@
+#endif
} else {
status->flag |= RX_FLAG_8023;
- }
+ mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
diff --git a/mt7996/main.c b/mt7996/main.c
-index 2ed66e6c..e5627c96 100644
+index 6fa4a65..804c0c1 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
-@@ -672,6 +672,10 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+@@ -696,6 +696,10 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7996_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -55,10 +55,10 @@
if (ret)
return ret;
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index b9f3dd8e..dc44edc1 100644
+index 013122f..3c535be 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -235,6 +235,34 @@ enum {
+@@ -205,6 +205,34 @@ enum {
SCS_ENABLE,
};
@@ -90,10 +90,10 @@
+};
+#endif
+
- struct mt7996_phy {
- struct mt76_phy *mt76;
- struct mt7996_dev *dev;
-@@ -285,6 +313,10 @@ struct mt7996_phy {
+ struct mt7996_wed_rro_addr {
+ u32 head_low;
+ u32 head_high : 4;
+@@ -264,6 +292,10 @@ struct mt7996_phy {
u8 spe_idx;
} test;
#endif
@@ -104,7 +104,7 @@
};
struct mt7996_dev {
-@@ -677,6 +709,9 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -687,6 +719,9 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
#ifdef CONFIG_MTK_VENDOR
void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
void mt7996_vendor_register(struct mt7996_phy *phy);
@@ -115,10 +115,10 @@
#ifdef CONFIG_MTK_DEBUG
diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index 08ecc2b3..8a021324 100644
+index b5ecbdf..f3b089d 100644
--- a/mt7996/vendor.c
+++ b/mt7996/vendor.c
-@@ -15,6 +15,32 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
+@@ -16,6 +16,32 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
[MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
};
@@ -151,7 +151,7 @@
static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
-@@ -62,6 +88,328 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+@@ -63,6 +89,328 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
return len;
}
@@ -480,7 +480,7 @@
static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
{
.info = {
-@@ -75,10 +423,24 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+@@ -76,10 +424,24 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
.policy = mu_ctrl_policy,
.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
},
@@ -506,7 +506,7 @@
+ spin_lock_init(&phy->amnt_lock);
}
diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index 8ac3ba8e..2078cafa 100644
+index 8ac3ba8..2078caf 100644
--- a/mt7996/vendor.h
+++ b/mt7996/vendor.h
@@ -4,6 +4,7 @@
@@ -561,5 +561,5 @@
+
#endif
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
deleted file mode 100644
index 7ddc56f..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
+++ /dev/null
@@ -1,220 +0,0 @@
-From b99c942620576c63baffd687090febea5ab2973d Mon Sep 17 00:00:00 2001
-From: mtk23510 <rudra.shahi@mediatek.com>
-Date: Wed, 26 Apr 2023 20:08:10 +0800
-Subject: [PATCH 1009/1015] wifi: mt76: mt7996: Beacon protection feature added
-
-Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
-Change-Id: I0149a65f71d844fc395c2827a54f9360492d181e
----
- mt76_connac_mcu.h | 16 +++++++++
- mt7996/main.c | 4 +++
- mt7996/mcu.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.h | 11 ++++++
- mt7996/mt7996.h | 2 ++
- 5 files changed, 119 insertions(+)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 42246fb9..a53fa138 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -415,6 +415,14 @@ struct sta_rec_he_6g_capa {
- u8 rsv[2];
- } __packed;
-
-+struct sta_rec_pn_info {
-+ __le16 tag;
-+ __le16 len;
-+ u8 pn[6];
-+ u8 tsc_type;
-+ u8 rsv;
-+} __packed;
-+
- struct sec_key {
- u8 cipher_id;
- u8 cipher_len;
-@@ -767,6 +775,7 @@ struct wtbl_raw {
- sizeof(struct sta_rec_sec) + \
- sizeof(struct sta_rec_ra_fixed) + \
- sizeof(struct sta_rec_he_6g_capa) + \
-+ sizeof(struct sta_rec_pn_info) + \
- sizeof(struct tlv) + \
- MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
-
-@@ -796,6 +805,7 @@ enum {
- STA_REC_HE_6G = 0x17,
- STA_REC_HE_V2 = 0x19,
- STA_REC_EHT = 0x22,
-+ STA_REC_PN_INFO = 0x26,
- STA_REC_HDRT = 0x28,
- STA_REC_HDR_TRANS = 0x2B,
- STA_REC_MAX_NUM
-@@ -1077,6 +1087,11 @@ enum mcu_cipher_type {
- MCU_CIPHER_GCMP_256,
- MCU_CIPHER_WAPI,
- MCU_CIPHER_BIP_CMAC_128,
-+ MCU_CIPHER_BIP_CMAC_256,
-+ MCU_CIPHER_BCN_PROT_CMAC_128,
-+ MCU_CIPHER_BCN_PROT_CMAC_256,
-+ MCU_CIPHER_BCN_PROT_GMAC_128,
-+ MCU_CIPHER_BCN_PROT_GMAC_256,
- };
-
- enum {
-@@ -1295,6 +1310,7 @@ enum {
- UNI_BSS_INFO_RATE = 11,
- UNI_BSS_INFO_QBSS = 15,
- UNI_BSS_INFO_SEC = 16,
-+ UNI_BSS_INFO_BCN_PROT = 17,
- UNI_BSS_INFO_TXCMD = 18,
- UNI_BSS_INFO_UAPSD = 19,
- UNI_BSS_INFO_PS = 21,
-diff --git a/mt7996/main.c b/mt7996/main.c
-index d40d3047..d3d10fab 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -400,6 +400,10 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- }
-
- mt76_wcid_key_setup(&dev->mt76, wcid, key);
-+
-+ if (key->keyidx == 6 || key->keyidx == 7)
-+ mt7996_mcu_bcn_prot_enable(dev, vif, key);
-+
- err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
- key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
- &msta->wcid, cmd);
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6add77da..53d2fc73 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2133,6 +2133,92 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
- return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
- }
-
-+static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-+ u8 *pn)
-+{
-+#define TSC_TYPE_BIGTK_PN 2
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct sta_rec_pn_info *pn_info;
-+ struct sk_buff *skb, *rskb;
-+ struct tlv *tlv;
-+ int ret;
-+
-+ skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
-+ pn_info = (struct sta_rec_pn_info *)tlv;
-+
-+ pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
-+ ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
-+ MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE), true, &rskb);
-+ if (ret)
-+ return ret;
-+
-+ skb_pull(rskb, 4);
-+
-+ pn_info = (struct sta_rec_pn_info *)rskb->data;
-+ if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
-+ memcpy(pn, pn_info->pn, 6);
-+
-+ dev_kfree_skb(rskb);
-+ return 0;
-+}
-+
-+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-+ struct ieee80211_key_conf *key)
-+{
-+#define WPA_BIGTK_MAX_LEN 32
-+ int len = sizeof(struct bss_req_hdr) + sizeof(struct mt7996_mcu_bcn_prot_tlv);
-+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ int ret;
-+ struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
-+ struct sk_buff *skb;
-+ struct tlv *tlv;
-+ u8 pn[6] = {0};
-+
-+ skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT,
-+ sizeof(*bcn_prot));
-+
-+ bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
-+
-+ ret = mt7996_mcu_get_pn(dev, vif, pn);
-+ if (ret) {
-+ dev_kfree_skb(skb);
-+ return ret;
-+ }
-+
-+ switch(key->cipher){
-+ case WLAN_CIPHER_SUITE_AES_CMAC:
-+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
-+ break;
-+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
-+ break;
-+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-+ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
-+ break;
-+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-+ default:
-+ dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
-+ dev_kfree_skb(skb);
-+ return -EOPNOTSUPP;
-+ }
-+
-+ pn[0]++;
-+ memcpy(bcn_prot->pn, pn, 6);
-+ bcn_prot->enable = 1;
-+ memcpy(bcn_prot->key, key->key, WPA_BIGTK_MAX_LEN);
-+ bcn_prot->key_id = key->keyidx;
-+
-+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+ MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
-+}
- int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
- struct ieee80211_vif *vif, bool enable)
- {
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index baffbcd7..f32ac153 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -262,6 +262,17 @@ struct bss_rate_tlv {
- u8 __rsv2[9];
- } __packed;
-
-+struct mt7996_mcu_bcn_prot_tlv {
-+ __le16 tag;
-+ __le16 len;
-+ u8 pn[6];
-+ u8 enable;
-+ u8 cipher_id;
-+ u8 key[32];
-+ u8 key_id;
-+ u8 __rsv[3];
-+} __packed;
-+
- struct bss_ra_tlv {
- __le16 tag;
- __le16 len;
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index c16bc8b4..94b62211 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -710,6 +710,8 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
- struct mt76_connac_sta_key_conf *sta_key_conf,
- struct ieee80211_key_conf *key, int mcu_cmd,
- struct mt76_wcid *wcid, enum set_key_cmd cmd);
-+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-+ struct ieee80211_key_conf *key);
- int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
similarity index 64%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
index 50db576..672885d 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
@@ -1,8 +1,8 @@
-From 75b684d04d569b5e83780d2296bed12d3785836c Mon Sep 17 00:00:00 2001
+From 786bd792b2a62dee5e4aca8aa09ed01be1731ec4 Mon Sep 17 00:00:00 2001
From: mtk23510 <rudra.shahi@mediatek.com>
Date: Fri, 24 Mar 2023 19:18:53 +0800
-Subject: [PATCH 1004/1015] wifi: mt76: mt7996: add driver support for wpa3 ocv
- and bp mt76
+Subject: [PATCH 42/98] wifi: mt76: mt7996: add driver support for wpa3 ocv and
+ bp mt76
Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
---
@@ -10,12 +10,12 @@
1 file changed, 2 insertions(+)
diff --git a/mt7996/init.c b/mt7996/init.c
-index 1d4359f0..40d610ae 100644
+index 1f4e84d..5940e41 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -373,6 +373,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+@@ -377,6 +377,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
@@ -23,5 +23,5 @@
!of_property_read_bool(mdev->dev->of_node,
"mediatek,disable-radar-background"))
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
index e185c11..1185d02 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
@@ -1,7 +1,7 @@
-From 47c64d6cac5ed78fab15cd4173ae8935605a3fca Mon Sep 17 00:00:00 2001
+From db3b9fa4bc9c70231b7237dee2f7bcf35c6135f2 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 31 Mar 2023 11:27:24 +0800
-Subject: [PATCH 1006/1015] wifi: mt76: testmode: add testmode pre-calibration
+Subject: [PATCH 43/98] wifi: mt76: testmode: add testmode pre-calibration
support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -22,7 +22,7 @@
12 files changed, 632 insertions(+), 23 deletions(-)
diff --git a/mac80211.c b/mac80211.c
-index 501325e9..6430e6ee 100644
+index f10ca90..9c582cb 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -7,27 +7,6 @@
@@ -54,7 +54,7 @@
CHAN2G(1, 2412),
CHAN2G(2, 2417),
diff --git a/mt76.h b/mt76.h
-index 31d5dc37..3341720c 100644
+index feb861c..fc69d3e 100644
--- a/mt76.h
+++ b/mt76.h
@@ -18,6 +18,27 @@
@@ -85,7 +85,7 @@
#define MT_MCU_RING_SIZE 32
#define MT_RX_BUF_SIZE 2048
#define MT_SKB_HEAD_LEN 256
-@@ -654,6 +675,7 @@ struct mt76_testmode_ops {
+@@ -694,6 +715,7 @@ struct mt76_testmode_ops {
int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
void (*reset_rx_stats)(struct mt76_phy *phy);
void (*tx_stop)(struct mt76_phy *phy);
@@ -94,20 +94,22 @@
#define MT_TM_FW_RX_COUNT BIT(0)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index e62f17ad..262abf88 100644
+index bbf600b..d65ecf0 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1011,6 +1011,8 @@ enum {
- MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
+@@ -1023,8 +1023,10 @@ enum {
MCU_UNI_EVENT_RDD_REPORT = 0x11,
- MCU_UNI_EVENT_THERMAL = 0x35,
+ MCU_UNI_EVENT_ROC = 0x27,
+ MCU_UNI_EVENT_TX_DONE = 0x2d,
+ MCU_UNI_EVENT_BF = 0x33,
+ MCU_UNI_EVENT_THERMAL = 0x35,
+ MCU_UNI_EVENT_NIC_CAPAB = 0x43,
+ MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
+ MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
+ MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
};
-
- #define MCU_UNI_CMD_EVENT BIT(1)
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index be0a34ae..60e98463 100644
+index e4c4b86..b88fd64 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
@@ -12,6 +12,42 @@ static bool testmode_enable;
@@ -153,7 +155,7 @@
static int mt7996_check_eeprom(struct mt7996_dev *dev)
{
u8 *eeprom = dev->mt76.eeprom.data;
-@@ -34,6 +70,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+@@ -36,6 +72,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
return MT7996_EEPROM_DEFAULT;
}
@@ -191,7 +193,7 @@
mt7996_eeprom_load_default(struct mt7996_dev *dev)
{
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 343e65e1..7ff290f4 100644
+index 343e65e..7ff290f 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
@@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
@@ -256,12 +258,12 @@
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 91f3103a..1fb7bae1 100644
+index a008c08..d6f4e22 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -523,6 +523,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
- case MCU_UNI_EVENT_THERMAL:
- mt7996_mcu_rx_thermal_notify(dev, skb);
+@@ -623,6 +623,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ case MCU_UNI_EVENT_ALL_STA_INFO:
+ mt7996_mcu_rx_all_sta_info_event(dev, skb);
break;
+#ifdef CONFIG_NL80211_TESTMODE
+ case MCU_UNI_EVENT_TESTMODE_CTRL:
@@ -272,10 +274,10 @@
break;
}
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index dc44edc1..9ab86eaf 100644
+index 3c535be..684c254 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -390,6 +390,9 @@ struct mt7996_dev {
+@@ -385,6 +385,9 @@ struct mt7996_dev {
struct dentry *debugfs_dir;
struct rchan *relay_fwlog;
@@ -285,7 +287,7 @@
struct {
u8 table_mask;
u8 n_agrt;
-@@ -522,6 +525,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
+@@ -521,6 +524,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
struct ieee80211_channel *chan);
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
@@ -293,7 +295,7 @@
int mt7996_dma_init(struct mt7996_dev *dev);
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
void mt7996_dma_prefetch(struct mt7996_dev *dev);
-@@ -602,6 +606,9 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+@@ -606,6 +610,9 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
void mt7996_mcu_scs_sta_poll(struct work_struct *work);
@@ -304,7 +306,7 @@
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
diff --git a/mt7996/testmode.c b/mt7996/testmode.c
-index 43eca4ef..7d36902e 100644
+index fb041c3..8ceea00 100644
--- a/mt7996/testmode.c
+++ b/mt7996/testmode.c
@@ -7,6 +7,8 @@
@@ -316,7 +318,7 @@
enum {
TM_CHANGED_TXPOWER,
-@@ -397,6 +399,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
+@@ -396,6 +398,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
}
}
@@ -753,7 +755,7 @@
static void
mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
{
-@@ -447,6 +879,10 @@ mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -452,6 +884,10 @@ mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
else if (prev_state == MT76_TM_STATE_OFF ||
state == MT76_TM_STATE_OFF)
mt7996_tm_init(phy, !(state == MT76_TM_STATE_OFF));
@@ -764,14 +766,14 @@
if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
-@@ -655,4 +1091,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
+@@ -671,4 +1107,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
.dump_stats = mt7996_tm_dump_stats,
.reset_rx_stats = mt7996_tm_reset_trx_stats,
.tx_stop = mt7996_tm_tx_stop,
+ .dump_precal = mt7996_tm_dump_precal,
};
diff --git a/mt7996/testmode.h b/mt7996/testmode.h
-index f00e51f4..778c9bc6 100644
+index e4d55a6..17c1456 100644
--- a/mt7996/testmode.h
+++ b/mt7996/testmode.h
@@ -34,6 +34,12 @@ enum bw_mapping_method {
@@ -833,10 +835,10 @@
RF_OPER_NORMAL,
RF_OPER_RF_TEST,
diff --git a/testmode.c b/testmode.c
-index fc68c2af..74bb26fa 100644
+index bbe8230..e66b54a 100644
--- a/testmode.c
+++ b/testmode.c
-@@ -626,6 +626,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -631,6 +631,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
mutex_lock(&dev->mutex);
@@ -856,10 +858,10 @@
err = -EINVAL;
diff --git a/testmode.h b/testmode.h
-index 8d0b9702..0c3b1393 100644
+index 141bb86..db8ff53 100644
--- a/testmode.h
+++ b/testmode.h
-@@ -215,6 +215,14 @@ enum mt76_testmode_state {
+@@ -219,6 +219,14 @@ enum mt76_testmode_state {
MT76_TM_STATE_TX_FRAMES,
MT76_TM_STATE_RX_FRAMES,
MT76_TM_STATE_TX_CONT,
@@ -875,7 +877,7 @@
/* keep last */
diff --git a/tools/fields.c b/tools/fields.c
-index e5cf7c53..b22b3fc8 100644
+index 055f90f..b012276 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
@@ -894,5 +896,5 @@
static const char * const testmode_tx_mode[] = {
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch
similarity index 86%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch
index 549344f..6d1a987 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch
@@ -1,7 +1,7 @@
-From 2cf8a9517919b39318eb1e878ca69418a499126a Mon Sep 17 00:00:00 2001
+From 2cd9ab05b3a16a92fb2552102b2a9c36834d1e7d Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 31 Mar 2023 11:36:34 +0800
-Subject: [PATCH 1007/1015] wifi: mt76: mt7996: add binfile mode support
+Subject: [PATCH 44/98] wifi: mt76: mt7996: add binfile mode support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
@@ -14,10 +14,10 @@
6 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/eeprom.c b/eeprom.c
-index aa889258..412740f0 100644
+index 437d8ca..89bb913 100644
--- a/eeprom.c
+++ b/eeprom.c
-@@ -104,6 +104,26 @@ out_put_node:
+@@ -159,6 +159,26 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
}
EXPORT_SYMBOL_GPL(mt76_get_of_eeprom);
@@ -45,10 +45,10 @@
mt76_eeprom_override(struct mt76_phy *phy)
{
diff --git a/mt76.h b/mt76.h
-index 3341720c..7d6e3241 100644
+index fc69d3e..0bf0177 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -894,6 +894,8 @@ struct mt76_dev {
+@@ -945,6 +945,8 @@ struct mt76_dev {
struct mt76_usb usb;
struct mt76_sdio sdio;
};
@@ -56,8 +56,8 @@
+ const char *bin_file_name;
};
- struct mt76_power_limits {
-@@ -1030,6 +1032,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
+ /* per-phy stats. */
+@@ -1190,6 +1192,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
int mt76_eeprom_init(struct mt76_dev *dev, int len);
void mt76_eeprom_override(struct mt76_phy *phy);
int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
@@ -66,7 +66,7 @@
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 60e98463..85d9e057 100644
+index b88fd64..ca91c69 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
@@ -61,8 +61,11 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
@@ -82,7 +82,7 @@
/* reserve for future variants */
if (dev->testmode_enable)
return MT7996_EEPROM_DEFAULT_TM;
-@@ -112,7 +115,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+@@ -114,7 +117,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
return ret;
if (!fw || !fw->data) {
@@ -94,7 +94,7 @@
ret = -EINVAL;
goto out;
}
-@@ -126,18 +132,45 @@ out:
+@@ -128,18 +134,45 @@ out:
return ret;
}
@@ -141,7 +141,7 @@
eeprom = dev->mt76.eeprom.data;
/* testmode enable priority: eeprom field > module parameter */
dev->testmode_enable = !mt7996_check_eeprom(dev) ? eeprom[MT_EE_TESTMODE_EN] :
-@@ -171,6 +204,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+@@ -173,6 +206,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
if (ret < 0)
return ret;
}
@@ -149,7 +149,7 @@
}
return mt7996_check_eeprom(dev);
-@@ -306,6 +340,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+@@ -309,6 +343,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
return ret;
dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
@@ -159,7 +159,7 @@
if (ret)
return ret;
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 7ff290f4..20dd8771 100644
+index 7ff290f..20dd877 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
@@ -99,6 +99,13 @@ enum mt7996_eeprom_band {
@@ -177,11 +177,11 @@
mt7996_get_channel_group_5g(int channel)
{
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 9ab86eaf..6ef6bad9 100644
+index 684c254..cda557e 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -380,6 +380,8 @@ struct mt7996_dev {
- bool has_eht:1;
+@@ -375,6 +375,8 @@ struct mt7996_dev {
+ } wed_rro;
bool testmode_enable;
+ bool bin_file_mode;
@@ -189,7 +189,7 @@
bool ibf;
u8 fw_debug_wm;
-@@ -519,6 +521,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
+@@ -518,6 +520,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
int mt7996_register_device(struct mt7996_dev *dev);
void mt7996_unregister_device(struct mt7996_dev *dev);
@@ -198,10 +198,10 @@
int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev);
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
-index 2aee3ab0..2ab2a8a8 100644
+index 57fcbab..82b2785 100644
--- a/mt7996/mtk_debugfs.c
+++ b/mt7996/mtk_debugfs.c
-@@ -2525,6 +2525,44 @@ static const struct file_operations mt7996_txpower_sku_fops = {
+@@ -2551,6 +2551,44 @@ static const struct file_operations mt7996_txpower_sku_fops = {
.llseek = default_llseek,
};
@@ -246,7 +246,7 @@
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
{
struct mt7996_dev *dev = phy->dev;
-@@ -2570,6 +2608,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+@@ -2596,6 +2634,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level);
debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
@@ -256,5 +256,5 @@
debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
mt7996_wtbl_read);
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
similarity index 90%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
index 6b18fb0..3aac8a9 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
@@ -1,7 +1,7 @@
-From f3ff5d5029a0a589e797dd2536070d3a3e4e30a6 Mon Sep 17 00:00:00 2001
+From 114d3abef99827bcc848e6aef393be79a7c34e71 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 1 Mar 2023 12:12:51 +0800
-Subject: [PATCH 1008/1015] wifi: mt76: mt7996: add normal mode pre-calibration
+Subject: [PATCH 45/98] wifi: mt76: mt7996: add normal mode pre-calibration
support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -16,22 +16,22 @@
7 files changed, 206 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 262abf88..42246fb9 100644
+index d65ecf0..762ac29 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1229,6 +1229,7 @@ enum {
- MCU_UNI_CMD_VOW = 0x37,
+@@ -1251,6 +1251,7 @@ enum {
+ MCU_UNI_CMD_PP = 0x38,
MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
+ MCU_UNI_CMD_PRECAL_RESULT = 0x47,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
- MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
+ MCU_UNI_CMD_PER_STA_INFO = 0x6d,
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 85d9e057..bee4a4b5 100644
+index ca91c69..56605de 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
-@@ -330,6 +330,25 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
+@@ -333,6 +333,25 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
return mt7996_eeprom_parse_band_config(phy);
}
@@ -57,7 +57,7 @@
int mt7996_eeprom_init(struct mt7996_dev *dev)
{
int ret;
-@@ -347,6 +366,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+@@ -350,6 +369,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
return ret;
}
@@ -69,7 +69,7 @@
if (ret < 0)
return ret;
diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 20dd8771..0f3f31d8 100644
+index 20dd877..0f3f31d 100644
--- a/mt7996/eeprom.h
+++ b/mt7996/eeprom.h
@@ -25,6 +25,8 @@ enum mt7996_eeprom_field {
@@ -82,10 +82,10 @@
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
diff --git a/mt7996/init.c b/mt7996/init.c
-index 40d610ae..31695090 100644
+index 5940e41..bf3479e 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -675,6 +675,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -826,6 +826,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
if (ret < 0)
return ret;
@@ -99,7 +99,7 @@
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
if (idx)
diff --git a/mt7996/main.c b/mt7996/main.c
-index e5627c96..d40d3047 100644
+index 804c0c1..7d1bd42 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -312,6 +312,12 @@ int mt7996_set_channel(struct mt7996_phy *phy)
@@ -116,10 +116,10 @@
if (ret)
goto out;
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 1fb7bae1..6add77da 100644
+index d6f4e22..695d5f0 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -3386,6 +3386,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
+@@ -3456,6 +3456,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
return 0;
}
@@ -293,11 +293,11 @@
{
#define NIC_CAP 3
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 6ef6bad9..c16bc8b4 100644
+index cda557e..80a10bf 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -607,6 +607,8 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
- void mt7996_mcu_exit(struct mt7996_dev *dev);
+@@ -611,6 +611,8 @@ void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
+int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev);
@@ -306,5 +306,5 @@
void mt7996_mcu_scs_sta_poll(struct work_struct *work);
#ifdef CONFIG_NL80211_TESTMODE
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
new file mode 100644
index 0000000..9a38681
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
@@ -0,0 +1,343 @@
+From a20311a499edde8f5b8e6b4bced55bd5e0f25884 Mon Sep 17 00:00:00 2001
+From: mtk23510 <rudra.shahi@mediatek.com>
+Date: Wed, 26 Apr 2023 20:08:10 +0800
+Subject: [PATCH 46/98] wifi: mt76: mt7996: Beacon protection feature added
+
+Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
+Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+---
+ mt76_connac_mcu.h | 24 ++++++++
+ mt7996/main.c | 14 +++--
+ mt7996/mcu.c | 138 +++++++++++++++++++++++++++++++++-------------
+ mt7996/mcu.h | 17 ++++++
+ mt7996/mt7996.h | 3 +-
+ 5 files changed, 153 insertions(+), 43 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 762ac29..42eb64c 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -418,6 +418,14 @@ struct sta_rec_he_6g_capa {
+ u8 rsv[2];
+ } __packed;
+
++struct sta_rec_pn_info {
++ __le16 tag;
++ __le16 len;
++ u8 pn[6];
++ u8 tsc_type;
++ u8 rsv;
++} __packed;
++
+ struct sec_key {
+ u8 cipher_id;
+ u8 cipher_len;
+@@ -770,6 +778,7 @@ struct wtbl_raw {
+ sizeof(struct sta_rec_sec) + \
+ sizeof(struct sta_rec_ra_fixed) + \
+ sizeof(struct sta_rec_he_6g_capa) + \
++ sizeof(struct sta_rec_pn_info) + \
+ sizeof(struct tlv) + \
+ MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
+
+@@ -800,6 +809,7 @@ enum {
+ STA_REC_HE_V2 = 0x19,
+ STA_REC_MLD = 0x20,
+ STA_REC_EHT = 0x22,
++ STA_REC_PN_INFO = 0x26,
+ STA_REC_HDRT = 0x28,
+ STA_REC_HDR_TRANS = 0x2B,
+ STA_REC_MAX_NUM
+@@ -1093,6 +1103,13 @@ enum mcu_cipher_type {
+ MCU_CIPHER_GCMP_256,
+ MCU_CIPHER_WAPI,
+ MCU_CIPHER_BIP_CMAC_128,
++ MCU_CIPHER_BIP_CMAC_256,
++ MCU_CIPHER_BCN_PROT_CMAC_128,
++ MCU_CIPHER_BCN_PROT_CMAC_256,
++ MCU_CIPHER_BCN_PROT_GMAC_128,
++ MCU_CIPHER_BCN_PROT_GMAC_256,
++ MCU_CIPHER_BIP_GMAC_128,
++ MCU_CIPHER_BIP_GMAC_256,
+ };
+
+ enum {
+@@ -1319,6 +1336,7 @@ enum {
+ UNI_BSS_INFO_RATE = 11,
+ UNI_BSS_INFO_QBSS = 15,
+ UNI_BSS_INFO_SEC = 16,
++ UNI_BSS_INFO_BCN_PROT = 17,
+ UNI_BSS_INFO_TXCMD = 18,
+ UNI_BSS_INFO_UAPSD = 19,
+ UNI_BSS_INFO_PS = 21,
+@@ -1779,6 +1797,12 @@ mt76_connac_mcu_get_cipher(int cipher)
+ return MCU_CIPHER_GCMP;
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ return MCU_CIPHER_GCMP_256;
++ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
++ return MCU_CIPHER_BIP_GMAC_128;
++ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
++ return MCU_CIPHER_BIP_GMAC_256;
++ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
++ return MCU_CIPHER_BIP_CMAC_256;
+ case WLAN_CIPHER_SUITE_SMS4:
+ return MCU_CIPHER_WAPI;
+ default:
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 7d1bd42..0ea006c 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -368,8 +368,10 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ /* fall back to sw encryption for unsupported ciphers */
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+- wcid_keyidx = &wcid->hw_key_idx2;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
++ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
++ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
++ wcid_keyidx = &wcid->hw_key_idx2;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+@@ -400,9 +402,13 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ }
+
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
+- err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
+- key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
+- &msta->wcid, cmd);
++
++ if (key->keyidx == 6 || key->keyidx == 7)
++ err = mt7996_mcu_bcn_prot_enable(dev, vif, key);
++ else
++ err = mt7996_mcu_add_key(&dev->mt76, vif, key,
++ MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
++ &msta->wcid, cmd);
+ out:
+ mutex_unlock(&dev->mt76.mutex);
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 695d5f0..1a1c732 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2118,7 +2118,6 @@ out:
+
+ static int
+ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
+- struct mt76_connac_sta_key_conf *sta_key_conf,
+ struct sk_buff *skb,
+ struct ieee80211_key_conf *key,
+ enum set_key_cmd cmd)
+@@ -2139,43 +2138,22 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
+ return -EOPNOTSUPP;
+
+ sec_key = &sec->key[0];
++ sec_key->wlan_idx = cpu_to_le16(wcid->idx);
++ sec_key->mgmt_prot = 0;
++ sec_key->cipher_id = cipher;
+ sec_key->cipher_len = sizeof(*sec_key);
+-
+- if (cipher == MCU_CIPHER_BIP_CMAC_128) {
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
+- sec_key->key_id = sta_key_conf->keyidx;
+- sec_key->key_len = 16;
+- memcpy(sec_key->key, sta_key_conf->key, 16);
+-
+- sec_key = &sec->key[1];
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
+- sec_key->cipher_len = sizeof(*sec_key);
+- sec_key->key_len = 16;
+- memcpy(sec_key->key, key->key, 16);
+- sec->n_cipher = 2;
+- } else {
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = cipher;
+- sec_key->key_id = key->keyidx;
+- sec_key->key_len = key->keylen;
+- memcpy(sec_key->key, key->key, key->keylen);
+-
+- if (cipher == MCU_CIPHER_TKIP) {
+- /* Rx/Tx MIC keys are swapped */
+- memcpy(sec_key->key + 16, key->key + 24, 8);
+- memcpy(sec_key->key + 24, key->key + 16, 8);
+- }
+-
+- /* store key_conf for BIP batch update */
+- if (cipher == MCU_CIPHER_AES_CCMP) {
+- memcpy(sta_key_conf->key, key->key, key->keylen);
+- sta_key_conf->keyidx = key->keyidx;
+- }
+-
+- sec->n_cipher = 1;
++ sec_key->key_id = key->keyidx;
++ sec_key->key_len = key->keylen;
++ sec_key->need_resp = 0;
++ memcpy(sec_key->key, key->key, key->keylen);
++
++ if (cipher == MCU_CIPHER_TKIP) {
++ /* Rx/Tx MIC keys are swapped */
++ memcpy(sec_key->key + 16, key->key + 24, 8);
++ memcpy(sec_key->key + 24, key->key + 16, 8);
+ }
++
++ sec->n_cipher = 1;
+ } else {
+ sec->n_cipher = 0;
+ }
+@@ -2184,7 +2162,6 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
+ }
+
+ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+- struct mt76_connac_sta_key_conf *sta_key_conf,
+ struct ieee80211_key_conf *key, int mcu_cmd,
+ struct mt76_wcid *wcid, enum set_key_cmd cmd)
+ {
+@@ -2197,13 +2174,98 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+- ret = mt7996_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd);
++ ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
+ if (ret)
+ return ret;
+
+ return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
+ }
+
++static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++ u8 *pn)
++{
++#define TSC_TYPE_BIGTK_PN 2
++ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++ struct sta_rec_pn_info *pn_info;
++ struct sk_buff *skb, *rskb;
++ struct tlv *tlv;
++ int ret;
++
++ skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
++ pn_info = (struct sta_rec_pn_info *)tlv;
++
++ pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
++ ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
++ MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE), true, &rskb);
++ if (ret)
++ return ret;
++
++ skb_pull(rskb, 4);
++
++ pn_info = (struct sta_rec_pn_info *)rskb->data;
++ if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
++ memcpy(pn, pn_info->pn, 6);
++
++ dev_kfree_skb(rskb);
++ return 0;
++}
++
++int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++ struct ieee80211_key_conf *key)
++{
++ int len = sizeof(struct bss_req_hdr) + sizeof(struct mt7996_mcu_bcn_prot_tlv);
++ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++ int ret;
++ struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
++ struct sk_buff *skb;
++ struct tlv *tlv;
++ u8 pn[6] = {0};
++
++ skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT,
++ sizeof(*bcn_prot));
++
++ bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
++
++ ret = mt7996_mcu_get_pn(dev, vif, pn);
++ if (ret) {
++ dev_kfree_skb(skb);
++ return ret;
++ }
++
++ switch (key->cipher) {
++ case WLAN_CIPHER_SUITE_AES_CMAC:
++ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
++ break;
++ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
++ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
++ break;
++ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
++ bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
++ break;
++ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
++ default:
++ dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
++ dev_kfree_skb(skb);
++ return -EOPNOTSUPP;
++ }
++
++ pn[0]++;
++ memcpy(bcn_prot->pn, pn, 6);
++ bcn_prot->enable = BP_SW_MODE;
++ memcpy(bcn_prot->key, key->key, WLAN_MAX_KEY_LEN);
++ bcn_prot->key_id = key->keyidx;
++
++ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
++ MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
++}
+ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
+ struct ieee80211_vif *vif, bool enable)
+ {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index c5c0a44..7808c35 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -310,6 +310,23 @@ struct bss_rate_tlv {
+ u8 __rsv2[9];
+ } __packed;
+
++enum {
++ BP_DISABLE,
++ BP_SW_MODE,
++ BP_HW_MODE,
++};
++
++struct mt7996_mcu_bcn_prot_tlv {
++ __le16 tag;
++ __le16 len;
++ u8 pn[6];
++ u8 enable;
++ u8 cipher_id;
++ u8 key[WLAN_MAX_KEY_LEN];
++ u8 key_id;
++ u8 __rsv[3];
++} __packed;
++
+ struct bss_ra_tlv {
+ __le16 tag;
+ __le16 len;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 80a10bf..9f99d13 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -712,9 +712,10 @@ int mt7996_init_debugfs(struct mt7996_phy *phy);
+ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len);
+ bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
+ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+- struct mt76_connac_sta_key_conf *sta_key_conf,
+ struct ieee80211_key_conf *key, int mcu_cmd,
+ struct mt76_wcid *wcid, enum set_key_cmd cmd);
++int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++ struct ieee80211_key_conf *key);
+ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch
deleted file mode 100644
index c01b398..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From 3a58791cef81709963d654d520fab9f1b7987e7b Mon Sep 17 00:00:00 2001
-From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
-Date: Thu, 11 May 2023 09:14:28 +0800
-Subject: [PATCH 1013/1015] wifi: mt76: mt7996: get tx_retries and tx_fails
- from txfree
-
-Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
----
- mt7996/mac.c | 20 +++++++++++++++-----
- mt7996/mac.h | 6 ++++--
- mt7996/main.c | 6 ++++++
- 3 files changed, 25 insertions(+), 7 deletions(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 3dc5cdae..bee4a8ae 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1240,6 +1240,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
- struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
- struct mt76_txwi_cache *txwi;
- struct ieee80211_sta *sta = NULL;
-+ struct mt76_wcid *wcid;
- LIST_HEAD(free_list);
- struct sk_buff *skb, *tmp;
- void *end = data + len;
-@@ -1258,7 +1259,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
- mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
- }
-
-- if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
-+ if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
- return;
-
- total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
-@@ -1274,10 +1275,9 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
- info = le32_to_cpu(*cur_info);
- if (info & MT_TXFREE_INFO_PAIR) {
- struct mt7996_sta *msta;
-- struct mt76_wcid *wcid;
- u16 idx;
-
-- idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
-+ idx = FIELD_GET(MT_TXFREE_INFO_MLD_ID, info);
- wcid = rcu_dereference(dev->mt76.wcid[idx]);
- sta = wcid_to_sta(wcid);
- if (!sta)
-@@ -1289,10 +1289,20 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
- continue;
-- }
-+ } else if (info & MT_TXFREE_INFO_HEADER) {
-+ if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) {
-+ u32 tx_retries = 0, tx_failed = 0;
-+
-+ tx_retries =
-+ FIELD_GET(MT_TXFREE_INFO_TX_COUNT, info) - 1;
-+ tx_failed = tx_retries +
-+ !!FIELD_GET(MT_TXFREE_INFO_STAT, info);
-
-- if (info & MT_TXFREE_INFO_HEADER)
-+ wcid->stats.tx_retries += tx_retries;
-+ wcid->stats.tx_failed += tx_failed;
-+ }
- continue;
-+ }
-
- for (i = 0; i < 2; i++) {
- msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index bc4e6c55..74ad1e81 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -256,11 +256,13 @@ enum tx_mgnt_type {
- #define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
- #define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
-
--#define MT_TXFREE1_VER GENMASK(18, 16)
-+#define MT_TXFREE1_VER GENMASK(19, 16)
-
- #define MT_TXFREE_INFO_PAIR BIT(31)
- #define MT_TXFREE_INFO_HEADER BIT(30)
--#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
-+#define MT_TXFREE_INFO_TX_COUNT GENMASK(27, 24)
-+#define MT_TXFREE_INFO_STAT GENMASK(29, 28)
-+#define MT_TXFREE_INFO_MLD_ID GENMASK(23, 12)
- #define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
-
- #define MT_TXS0_BW GENMASK(31, 29)
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 71c346cb..f0bdec6b 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -1024,6 +1024,12 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
- sinfo->txrate.flags = txrate->flags;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
-
-+ sinfo->tx_failed = msta->wcid.stats.tx_failed;
-+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
-+
-+ sinfo->tx_retries = msta->wcid.stats.tx_retries;
-+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
-+
- sinfo->ack_signal = (s8)msta->ack_signal;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
-
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
index 999d9ba..16439d4 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
@@ -1,8 +1,8 @@
-From 639385416a573ae5ce631a0323c5541dea3e406c Mon Sep 17 00:00:00 2001
+From 9bbc79e25d5fe7c14ec520413f4fb0625af9c630 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 22 Mar 2023 11:19:52 +0800
-Subject: [PATCH 1010/1015] wifi: mt76: testmode: add testmode ZWDFS
- verification support
+Subject: [PATCH 47/98] wifi: mt76: testmode: add testmode ZWDFS verification
+ support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
@@ -15,10 +15,10 @@
6 files changed, 326 insertions(+), 12 deletions(-)
diff --git a/mt76.h b/mt76.h
-index 7d6e3241..5b442691 100644
+index 0bf0177..0096c7f 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -732,6 +732,14 @@ struct mt76_testmode_data {
+@@ -774,6 +774,14 @@ struct mt76_testmode_data {
} cfg;
u8 aid;
@@ -34,22 +34,22 @@
struct mt76_vif {
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 94b62211..abdbb1ef 100644
+index 9f99d13..7269076 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -295,6 +295,7 @@ struct mt7996_phy {
+@@ -272,6 +272,7 @@ struct mt7996_phy {
- struct mib_stats mib;
+ struct mt76_mib_stats mib;
struct mt76_channel_state state_ts;
+ struct delayed_work ipi_work;
bool has_aux_rx;
diff --git a/mt7996/testmode.c b/mt7996/testmode.c
-index 7d36902e..ba3cd802 100644
+index 8ceea00..c52bf41 100644
--- a/mt7996/testmode.c
+++ b/mt7996/testmode.c
-@@ -16,6 +16,12 @@ enum {
+@@ -17,6 +17,12 @@ enum {
TM_CHANGED_TX_LENGTH,
TM_CHANGED_TX_TIME,
TM_CHANGED_CFG,
@@ -62,7 +62,7 @@
/* must be last */
NUM_TM_CHANGED
-@@ -27,20 +33,31 @@ static const u8 tm_change_map[] = {
+@@ -29,20 +35,31 @@ static const u8 tm_change_map[] = {
[TM_CHANGED_TX_LENGTH] = MT76_TM_ATTR_TX_LENGTH,
[TM_CHANGED_TX_TIME] = MT76_TM_ATTR_TX_TIME,
[TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
@@ -105,7 +105,7 @@
};
if (width >= ARRAY_SIZE(width_to_bw))
-@@ -217,6 +234,9 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en)
+@@ -216,6 +233,9 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en)
/* use firmware counter for RX stats */
phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
@@ -115,7 +115,7 @@
}
static void
-@@ -829,6 +849,204 @@ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -828,6 +848,204 @@ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
@@ -320,7 +320,7 @@
static void
mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
{
-@@ -853,6 +1071,14 @@ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+@@ -858,6 +1076,14 @@ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
mt7996_tm_set(dev, func_idx, td->cfg.type);
}
@@ -336,7 +336,7 @@
static int
diff --git a/mt7996/testmode.h b/mt7996/testmode.h
-index 778c9bc6..09f81d39 100644
+index 17c1456..57fde8c 100644
--- a/mt7996/testmode.h
+++ b/mt7996/testmode.h
@@ -27,9 +27,15 @@ enum {
@@ -355,7 +355,7 @@
NUM_BW_MAP,
};
-@@ -308,4 +314,42 @@ struct mt7996_tm_rx_event {
+@@ -310,4 +316,42 @@ struct mt7996_tm_rx_event {
};
} __packed;
@@ -399,10 +399,10 @@
+
#endif
diff --git a/testmode.c b/testmode.c
-index 74bb26fa..22d6afd4 100644
+index e66b54a..bce3a9c 100644
--- a/testmode.c
+++ b/testmode.c
-@@ -25,6 +25,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+@@ -27,6 +27,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
[MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
[MT76_TM_ATTR_DRV_DATA] = { .type = NLA_NESTED },
@@ -416,7 +416,7 @@
};
EXPORT_SYMBOL_GPL(mt76_tm_policy);
-@@ -451,6 +458,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -456,6 +463,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (tb[MT76_TM_ATTR_TX_RATE_IDX])
td->tx_rate_idx = nla_get_u8(tb[MT76_TM_ATTR_TX_RATE_IDX]);
@@ -426,7 +426,7 @@
if (mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_MODE], &td->tx_rate_mode,
0, MT76_TM_TX_MODE_MAX) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_NSS], &td->tx_rate_nss,
-@@ -466,7 +476,14 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -471,7 +481,14 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
&td->tx_duty_cycle, 0, 99) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
&td->tx_power_control, 0, 1) ||
@@ -442,9 +442,9 @@
goto out;
if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -671,6 +688,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
+@@ -677,6 +694,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
+ nla_put_u8(msg, MT76_TM_ATTR_SKU_EN, td->sku_en) ||
nla_put_u8(msg, MT76_TM_ATTR_AID, td->aid) ||
+ nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CH, td->offchan_ch) ||
+ nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH, td->offchan_center_ch) ||
@@ -453,7 +453,7 @@
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
diff --git a/tools/fields.c b/tools/fields.c
-index b22b3fc8..55854a6f 100644
+index b012276..77696ce 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -35,6 +35,15 @@ static const char * const testmode_tx_mode[] = {
@@ -472,7 +472,7 @@
static void print_enum(const struct tm_field *field, struct nlattr *attr)
{
unsigned int i = nla_get_u8(attr);
-@@ -387,6 +396,12 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+@@ -390,6 +399,12 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
FIELD(u8, AID, "aid"),
FIELD(u8, RU_ALLOC, "ru_alloc"),
FIELD(u8, RU_IDX, "ru_idx"),
@@ -486,5 +486,5 @@
FIELD_NESTED_RO(STATS, stats, "",
.print_extra = print_extra_stats),
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-single-sku.patch
similarity index 76%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-single-sku.patch
index 0fcae6a..14514e2 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-single-sku.patch
@@ -1,27 +1,27 @@
-From 0d9ff0aa7afe37146c6015e416d9b944b4bb16f5 Mon Sep 17 00:00:00 2001
+From d07d8b3b246b974d7ae4ad9bdfc676438cb45fec Mon Sep 17 00:00:00 2001
From: "Allen.Ye" <allen.ye@mediatek.com>
-Date: Tue, 18 Apr 2023 15:56:22 +0800
-Subject: [PATCH 1011/1015] wifi: mt76: mt7996: add single sku
+Date: Mon, 10 Jul 2023 19:56:16 +0800
+Subject: [PATCH 48/98] wifi: mt76: mt7996: add single sku
Add single sku and default enable sku.
Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
---
- eeprom.c | 38 ++++++++++++++++++--
- mt76.h | 10 ++++++
+ eeprom.c | 50 +++++++++++++++++++++++---
+ mt76.h | 9 +++++
mt76_connac_mcu.c | 2 +-
mt7996/init.c | 2 ++
- mt7996/main.c | 15 ++++++++
+ mt7996/main.c | 16 +++++++++
mt7996/mcu.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.h | 12 +++++++
mt7996/mt7996.h | 2 ++
- 8 files changed, 169 insertions(+), 4 deletions(-)
+ 8 files changed, 179 insertions(+), 6 deletions(-)
diff --git a/eeprom.c b/eeprom.c
-index 412740f0..3abefb5a 100644
+index 89bb913..bd662dd 100644
--- a/eeprom.c
+++ b/eeprom.c
-@@ -301,6 +301,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
+@@ -356,6 +356,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
struct ieee80211_channel *chan,
struct mt76_power_limits *dest,
@@ -29,15 +29,19 @@
s8 target_power)
{
struct mt76_dev *dev = phy->dev;
-@@ -308,16 +309,17 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+@@ -363,16 +364,20 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
const __be32 *val;
char name[16];
u32 mcs_rates = dev->drv->mcs_rates;
- u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
char band;
size_t len;
- s8 max_power = 0;
+- s8 max_power = 0;
++ s8 max_power = -127;
++ s8 max_power_backoff = -127;
s8 txs_delta;
++ int n_chains = hweight8(phy->antenna_mask);
++ s8 target_power_combine = target_power + mt76_tx_power_nss_delta(n_chains);
if (!mcs_rates)
- mcs_rates = 10;
@@ -49,7 +53,7 @@
if (!IS_ENABLED(CONFIG_OF))
return target_power;
-@@ -365,11 +367,41 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+@@ -420,12 +425,47 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
ARRAY_SIZE(dest->mcs), val, len,
target_power, txs_delta, &max_power);
@@ -59,85 +63,91 @@
ARRAY_SIZE(dest->ru), val, len,
target_power, txs_delta, &max_power);
-+ val = mt76_get_of_array(np, "rates-eht-ru", &len, ARRAY_SIZE(dest->eht_ru[0]) + 1);
-+ mt76_apply_multi_array_limit(dest->eht_ru[0], ARRAY_SIZE(dest->eht_ru[0]),
-+ ARRAY_SIZE(dest->eht_ru), val, len,
+- return max_power;
++ val = mt76_get_of_array(np, "rates-eht", &len, ARRAY_SIZE(dest->eht[0]) + 1);
++ mt76_apply_multi_array_limit(dest->eht[0], ARRAY_SIZE(dest->eht[0]),
++ ARRAY_SIZE(dest->eht), val, len,
+ target_power, txs_delta, &max_power);
+
+ if (dest_path == NULL)
+ return max_power;
+
++ max_power_backoff = max_power;
++
+ val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest_path->cck));
+ mt76_apply_array_limit(dest_path->cck, ARRAY_SIZE(dest_path->cck), val,
-+ target_power, txs_delta, &max_power);
++ target_power_combine, txs_delta, &max_power_backoff);
+
+ val = mt76_get_of_array(np, "paths-ofdm", &len, ARRAY_SIZE(dest_path->ofdm));
+ mt76_apply_array_limit(dest_path->ofdm, ARRAY_SIZE(dest_path->ofdm), val,
-+ target_power, txs_delta, &max_power);
++ target_power_combine, txs_delta, &max_power_backoff);
+
+ val = mt76_get_of_array(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest_path->ofdm_bf));
+ mt76_apply_array_limit(dest_path->ofdm_bf, ARRAY_SIZE(dest_path->ofdm_bf), val,
-+ target_power, txs_delta, &max_power);
++ target_power_combine, txs_delta, &max_power_backoff);
+
+ val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest_path->ru[0]) + 1);
+ mt76_apply_multi_array_limit(dest_path->ru[0], ARRAY_SIZE(dest_path->ru[0]),
+ ARRAY_SIZE(dest_path->ru), val, len,
-+ target_power, txs_delta, &max_power);
++ target_power_combine, txs_delta, &max_power_backoff);
+
+ val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest_path->ru_bf[0]) + 1);
+ mt76_apply_multi_array_limit(dest_path->ru_bf[0], ARRAY_SIZE(dest_path->ru_bf[0]),
+ ARRAY_SIZE(dest_path->ru_bf), val, len,
-+ target_power, txs_delta, &max_power);
++ target_power_combine, txs_delta, &max_power_backoff);
++
++ if (max_power_backoff == target_power_combine)
++ return max_power;
+
- return max_power;
++ return max_power_backoff;
}
EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
+
diff --git a/mt76.h b/mt76.h
-index 5b442691..8abb6f41 100644
+index 0096c7f..d59a1f5 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -911,6 +911,15 @@ struct mt76_power_limits {
- s8 ofdm[8];
- s8 mcs[4][10];
- s8 ru[7][12];
-+ s8 eht_ru[16][16];
-+};
-+
+@@ -1060,6 +1060,14 @@ struct mt76_power_limits {
+ s8 eht[16][16];
+ };
+
+struct mt76_power_path_limits {
+ s8 cck[5];
+ s8 ofdm[5];
+ s8 ofdm_bf[4];
+ s8 ru[16][15];
+ s8 ru_bf[16][15];
- };
-
++};
++
struct mt76_ethtool_worker_info {
-@@ -1493,6 +1502,7 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);
+ u64 *data;
+ int idx;
+@@ -1655,6 +1663,7 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);
s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
struct ieee80211_channel *chan,
struct mt76_power_limits *dest,
+ struct mt76_power_path_limits *dest_path,
s8 target_power);
- static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
+ static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q)
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index c24dac10..ca7b6a6f 100644
+index 236cfea..214a526 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
-@@ -2235,7 +2235,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
+@@ -2269,7 +2269,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
sar_power = mt76_get_sar_power(phy, &chan, reg_power);
- mt76_get_rate_power_limits(phy, &chan, &limits,
+ mt76_get_rate_power_limits(phy, &chan, limits,
- sar_power);
+ NULL, sar_power);
tx_power_tlv.last_msg = ch_list[idx] == last_ch;
sku_tlbv.channel = ch_list[idx];
diff --git a/mt7996/init.c b/mt7996/init.c
-index 31695090..a6caf4f1 100644
+index bf3479e..ad93927 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
-@@ -294,6 +294,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+@@ -295,6 +295,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
int nss_delta = mt76_tx_power_nss_delta(nss);
int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
struct mt76_power_limits limits;
@@ -145,7 +155,7 @@
for (i = 0; i < sband->n_channels; i++) {
struct ieee80211_channel *chan = &sband->channels[i];
-@@ -302,6 +303,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+@@ -303,6 +304,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
target_power += pwr_delta;
target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
&limits,
@@ -154,7 +164,7 @@
target_power += nss_delta;
target_power = DIV_ROUND_UP(target_power, 2);
diff --git a/mt7996/main.c b/mt7996/main.c
-index d3d10fab..71c346cb 100644
+index 0ea006c..9e3e4ed 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -77,6 +77,15 @@ int mt7996_run(struct ieee80211_hw *hw)
@@ -173,7 +183,7 @@
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-@@ -427,6 +436,12 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
+@@ -429,6 +438,12 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
ieee80211_wake_queues(hw);
}
@@ -186,11 +196,19 @@
mutex_lock(&dev->mt76.mutex);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+@@ -1005,6 +1020,7 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+ mt76_set_stream_caps(phy->mt76, true);
+ mt7996_set_stream_vht_txbf_caps(phy);
+ mt7996_set_stream_he_eht_caps(phy);
++ mt7996_mcu_set_txpower_sku(phy);
+
+ mutex_unlock(&dev->mt76.mutex);
+
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 53d2fc73..aefbdca6 100644
+index 1a1c732..c87cb1a 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -4616,6 +4616,98 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+@@ -4708,6 +4708,98 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
&req, sizeof(req), false);
}
@@ -249,7 +267,7 @@
+ skb_put_data(skb, &la.ru[0], sizeof(la.ru));
+
+ /* eht */
-+ skb_put_data(skb, &la.eht_ru[0], sizeof(la.eht_ru));
++ skb_put_data(skb, &la.eht[0], sizeof(la.eht));
+
+ /* padding */
+ skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
@@ -290,10 +308,10 @@
void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
{
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index f32ac153..1d2b7c58 100644
+index 7808c35..6fc5ab3 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -657,6 +657,18 @@ enum {
+@@ -777,6 +777,18 @@ enum {
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
MT7996_BEACON_UPDATE_SIZE)
@@ -313,18 +331,18 @@
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index abdbb1ef..d15bd950 100644
+index 7269076..34c8fe6 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -61,6 +61,7 @@
+@@ -64,6 +64,7 @@
#define MT7996_BUILD_TIME_LEN 24
#define MT7996_SKU_RATE_NUM 417
+#define MT7996_SKU_PATH_NUM 494
- struct mt7996_vif;
- struct mt7996_sta;
-@@ -610,6 +611,7 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ #define MT7996_RRO_MAX_SESSION 1024
+ #define MT7996_RRO_WINDOW_MAX_LEN 1024
+@@ -614,6 +615,7 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev);
int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
@@ -333,5 +351,5 @@
void mt7996_mcu_scs_sta_poll(struct work_struct *work);
#ifdef CONFIG_NL80211_TESTMODE
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
similarity index 87%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
index c5ea448..37717c3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
@@ -1,7 +1,7 @@
-From a048ff567915954ca9cc68ef94c9a7786542b5d9 Mon Sep 17 00:00:00 2001
+From 8d1ba9d8e0f80eedcdf14d29dbca9c3cbd8589dc Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Wed, 3 May 2023 05:08:07 +0800
-Subject: [PATCH 1012/1015] wifi: mt76: mt7996: add vendor cmd to get available
+Subject: [PATCH 49/98] wifi: mt76: mt7996: add vendor cmd to get available
color bitmap
Add a vendor cmd to notify user space available color bitmap.
@@ -14,10 +14,10 @@
2 files changed, 47 insertions(+)
diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index 8a021324..73f613aa 100644
+index f3b089d..3910157 100644
--- a/mt7996/vendor.c
+++ b/mt7996/vendor.c
-@@ -34,6 +34,11 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
+@@ -35,6 +35,11 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
[MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED },
};
@@ -29,7 +29,7 @@
struct mt7996_amnt_data {
u8 idx;
u8 addr[ETH_ALEN];
-@@ -409,6 +414,26 @@ mt7966_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+@@ -410,6 +415,26 @@ mt7966_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
return len + 1;
}
@@ -56,7 +56,7 @@
static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
{
-@@ -435,6 +460,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+@@ -436,6 +461,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
.policy = amnt_ctrl_policy,
.maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX,
},
@@ -75,7 +75,7 @@
void mt7996_vendor_register(struct mt7996_phy *phy)
diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index 2078cafa..eec9e74a 100644
+index 2078caf..eec9e74 100644
--- a/mt7996/vendor.h
+++ b/mt7996/vendor.h
@@ -6,6 +6,7 @@
@@ -103,5 +103,5 @@
#endif
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
similarity index 88%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
index 1b22e9a..da8c4bd 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
@@ -1,7 +1,7 @@
-From 97144fb0d20ba67ec6c3a022ed5a39bc95ed40e9 Mon Sep 17 00:00:00 2001
+From 7556e60ec860e301a053dad4b16b7e88ccd9baa7 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Fri, 19 May 2023 14:56:07 +0800
-Subject: [PATCH 1014/1015] wifi: mt76: mt7996: add debugfs for fw coredump.
+Subject: [PATCH 50/98] wifi: mt76: mt7996: add debugfs for fw coredump.
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
---
@@ -12,7 +12,7 @@
4 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 8a513f46..49c815a5 100644
+index 92aa164..2c11837 100644
--- a/mt7996/debugfs.c
+++ b/mt7996/debugfs.c
@@ -84,6 +84,8 @@ mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
@@ -64,10 +64,10 @@
desc += scnprintf(buff + desc, bufsz - desc,
"\nlet's dump firmware SER statistics...\n");
diff --git a/mt7996/mac.c b/mt7996/mac.c
-index bee4a8ae..993b43ce 100644
+index ee17d59..37cc94e 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -2157,15 +2157,36 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2021,15 +2021,36 @@ void mt7996_mac_dump_work(struct work_struct *work)
struct mt7996_dev *dev;
dev = container_of(work, struct mt7996_dev, dump_work);
@@ -106,8 +106,8 @@
+
void mt7996_reset(struct mt7996_dev *dev)
{
- dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n",
-@@ -2187,6 +2208,7 @@ void mt7996_reset(struct mt7996_dev *dev)
+ if (!dev->recovery.hw_init_done)
+@@ -2047,6 +2068,7 @@ void mt7996_reset(struct mt7996_dev *dev)
mt7996_irq_disable(dev, MT_INT_MCU_CMD);
queue_work(dev->mt76.wq, &dev->dump_work);
@@ -116,10 +116,10 @@
}
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 1d2b7c58..a0cbf922 100644
+index 6fc5ab3..989a2ff 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -780,7 +780,11 @@ enum {
+@@ -900,7 +900,11 @@ enum {
UNI_CMD_SER_SET_RECOVER_L3_BF,
UNI_CMD_SER_SET_RECOVER_L4_MDP,
UNI_CMD_SER_SET_RECOVER_FULL,
@@ -132,10 +132,10 @@
UNI_CMD_SER_ENABLE = 1,
UNI_CMD_SER_SET,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index d15bd950..e371964b 100644
+index 34c8fe6..9b110cf 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -76,6 +76,14 @@ enum mt7996_ram_type {
+@@ -100,6 +100,14 @@ enum mt7996_ram_type {
__MT7996_RAM_TYPE_MAX,
};
@@ -150,7 +150,7 @@
enum mt7996_txq_id {
MT7996_TXQ_FWDL = 16,
MT7996_TXQ_MCU_WM,
-@@ -361,6 +369,7 @@ struct mt7996_dev {
+@@ -342,6 +350,7 @@ struct mt7996_dev {
/* protects coredump data */
struct mutex dump_mutex;
@@ -158,7 +158,7 @@
#ifdef CONFIG_DEV_COREDUMP
struct {
struct mt7996_crash_data *crash_data[__MT7996_RAM_TYPE_MAX];
-@@ -540,6 +549,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+@@ -541,6 +550,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
struct ieee80211_supported_band *sband);
int mt7996_txbf_init(struct mt7996_dev *dev);
void mt7996_reset(struct mt7996_dev *dev);
@@ -167,5 +167,5 @@
int mt7996_mcu_init(struct mt7996_dev *dev);
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
similarity index 80%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
index 33432ff..dc0b0c3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
@@ -1,8 +1,8 @@
-From 0d4c8fc47472e0acb7f823f483bc8b83c8a9f235 Mon Sep 17 00:00:00 2001
+From a928c6df5edd9920b4293de6d1216461952aec27 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 6 Jun 2023 16:57:10 +0800
-Subject: [PATCH 1015/1015] wifi: mt76: mt7996: add support for runtime set
- in-band discovery
+Subject: [PATCH 51/98] wifi: mt76: mt7996: add support for runtime set in-band
+ discovery
with this patch, AP can runtime set inband discovery via hostapd_cli
@@ -17,10 +17,10 @@
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index aefbdca6..59f22f6d 100644
+index c87cb1a..722c435 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -2438,8 +2438,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+@@ -2484,8 +2484,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
if (IS_ERR(rskb))
return PTR_ERR(rskb);
@@ -30,7 +30,7 @@
interval = vif->bss_conf.fils_discovery.max_interval;
skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
-@@ -2475,7 +2474,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+@@ -2521,7 +2520,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
discov->tx_interval = interval;
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
@@ -40,5 +40,5 @@
buf = (u8 *)tlv + sizeof(*discov);
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch
new file mode 100644
index 0000000..06fc5e8
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch
@@ -0,0 +1,392 @@
+From 140f810c788ffccc605fa979635c9be2db4b9748 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Thu, 8 Jun 2023 20:21:04 +0800
+Subject: [PATCH 52/98] wifi: mt76: mt7996: add vendor subcmd EDCCA ctrl enable
+
+---
+ mt7996/main.c | 3 ++
+ mt7996/mcu.h | 2 +
+ mt7996/mt7996.h | 11 ++++
+ mt7996/mtk_mcu.c | 86 ++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h | 15 ++++++
+ mt7996/vendor.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 33 ++++++++++++
+ 7 files changed, 282 insertions(+)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 9e3e4ed..d928564 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -431,6 +431,9 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
+ int ret;
+
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
++ ret = mt7996_mcu_edcca_enable(phy, true);
++ if (ret)
++ return ret;
+ ieee80211_stop_queues(hw);
+ ret = mt7996_set_channel(phy);
+ if (ret)
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 989a2ff..bb876f3 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -791,6 +791,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
+
+ enum {
+ UNI_BAND_CONFIG_RADIO_ENABLE,
++ UNI_BAND_CONFIG_EDCCA_ENABLE = 0x05,
++ UNI_BAND_CONFIG_EDCCA_THRESHOLD = 0x06,
+ UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
+ };
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 9b110cf..8fd29d7 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -750,6 +750,17 @@ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
+ struct ieee80211_sta *sta);
+ #endif
+
++int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
++int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set);
++
++enum edcca_bw_id {
++ EDCCA_BW_20 = 0,
++ EDCCA_BW_40,
++ EDCCA_BW_80,
++ EDCCA_BW_160,
++ EDCCA_MAX_BW_NUM,
++};
++
+ #ifdef CONFIG_MTK_DEBUG
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
+ #endif
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index f772243..048c534 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -38,4 +38,90 @@ int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *even
+ return 0;
+ }
+
++int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable)
++{
++ struct mt7996_dev *dev = phy->dev;
++ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
++ enum nl80211_band band = chandef->chan->band;
++ struct {
++ u8 band_idx;
++ u8 _rsv[3];
++
++ __le16 tag;
++ __le16 len;
++ u8 enable;
++ u8 std;
++ u8 _rsv2[2];
++ } __packed req = {
++ .band_idx = phy->mt76->band_idx,
++ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_ENABLE),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .enable = enable,
++ .std = EDCCA_DEFAULT,
++ };
++
++ switch (dev->mt76.region) {
++ case NL80211_DFS_JP:
++ req.std = EDCCA_JAPAN;
++ break;
++ case NL80211_DFS_FCC:
++ if (band == NL80211_BAND_6GHZ)
++ req.std = EDCCA_FCC;
++ break;
++ case NL80211_DFS_ETSI:
++ if (band == NL80211_BAND_6GHZ)
++ req.std = EDCCA_ETSI;
++ break;
++ default:
++ break;
++ }
++
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
++ &req, sizeof(req), true);
++}
++
++int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set)
++{
++ struct {
++ u8 band_idx;
++ u8 _rsv[3];
++
++ __le16 tag;
++ __le16 len;
++ u8 threshold[4];
++ bool init;
++ } __packed *res, req = {
++ .band_idx = phy->mt76->band_idx,
++ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_THRESHOLD),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .init = false,
++ };
++ struct sk_buff *skb;
++ int ret;
++ int i;
++
++ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
++ req.threshold[i] = value[i];
++
++ if (set)
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
++ &req, sizeof(req), true);
++
++ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76,
++ MCU_WM_UNI_CMD_QUERY(BAND_CONFIG),
++ &req, sizeof(req), true, &skb);
++
++ if (ret)
++ return ret;
++
++ res = (void *)skb->data;
++
++ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
++ value[i] = res->threshold[i];
++
++ dev_kfree_skb(skb);
++
++ return 0;
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index beb1aba..9c0db87 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -89,6 +89,21 @@ enum txpower_event {
+ UNI_TXPOWER_PHY_RATE_INFO = 5,
+ };
+
++enum {
++ EDCCA_CTRL_SET_EN = 0,
++ EDCCA_CTRL_SET_THRES,
++ EDCCA_CTRL_GET_EN,
++ EDCCA_CTRL_GET_THRES,
++ EDCCA_CTRL_NUM,
++};
++
++enum {
++ EDCCA_DEFAULT = 0,
++ EDCCA_FCC = 1,
++ EDCCA_ETSI = 2,
++ EDCCA_JAPAN = 3
++};
++
+ #endif
+
+ #endif
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 3910157..9f333d0 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -40,6 +40,26 @@ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
+ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
+ };
+
++static const struct nla_policy
++edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_S8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL] = { .type = NLA_U8 },
++};
++
++static const struct nla_policy
++edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
++ [MTK_VENDOR_ATTR_EDCCA_DUMP_MODE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL] = { .type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ u8 idx;
+ u8 addr[ETH_ALEN];
+@@ -436,6 +456,106 @@ mt7996_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev
+ return len;
+ }
+
++static int mt7996_vendor_edcca_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
++ const void *data, int data_len)
++{
++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++ struct mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
++ int err;
++ u8 edcca_mode;
++ u8 edcca_value[EDCCA_MAX_BW_NUM];
++
++ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
++ edcca_ctrl_policy, NULL);
++ if (err)
++ return err;
++
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
++ return -EINVAL;
++
++ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
++ if (edcca_mode == EDCCA_CTRL_SET_EN) {
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL])
++ return -EINVAL;
++
++ edcca_value[0] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
++
++ err = mt7996_mcu_edcca_enable(phy, !!edcca_value[0]);
++ if (err)
++ return err;
++ } else if (edcca_mode == EDCCA_CTRL_SET_THRES) {
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] ||
++ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] ||
++ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] ||
++ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]) {
++ return -EINVAL;
++ }
++ edcca_value[EDCCA_BW_20] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
++ edcca_value[EDCCA_BW_40] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL]);
++ edcca_value[EDCCA_BW_80] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL]);
++ edcca_value[EDCCA_BW_160] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]);
++
++ err = mt7996_mcu_edcca_threshold_ctrl(phy, edcca_value, true);
++
++ if (err)
++ return err;
++ } else {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static int
++mt7996_vendor_edcca_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 mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
++ int err;
++ u8 edcca_mode;
++ u8 value[EDCCA_MAX_BW_NUM];
++
++ if (*storage == 1)
++ return -ENOENT;
++ *storage = 1;
++
++ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
++ edcca_ctrl_policy, NULL);
++ if (err)
++ return err;
++
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
++ return -EINVAL;
++
++ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
++
++ if (edcca_mode != EDCCA_CTRL_GET_THRES)
++ return -EINVAL;
++
++ err = mt7996_mcu_edcca_threshold_ctrl(phy, value, false);
++
++ if (err)
++ return err;
++
++ if (nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL, value[EDCCA_BW_20]) ||
++ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL, value[EDCCA_BW_40]) ||
++ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL, value[EDCCA_BW_80]) ||
++ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL, value[EDCCA_BW_160]))
++ return -ENOMEM;
++
++ return EDCCA_MAX_BW_NUM;
++}
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ {
+ .info = {
+@@ -472,6 +592,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ .policy = bss_color_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
+ },
++ {
++ .info = {
++ .vendor_id = MTK_NL80211_VENDOR_ID,
++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL,
++ },
++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++ WIPHY_VENDOR_CMD_NEED_RUNNING,
++ .doit = mt7996_vendor_edcca_ctrl,
++ .dumpit = mt7996_vendor_edcca_ctrl_dump,
++ .policy = edcca_ctrl_policy,
++ .maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
++ },
+ };
+
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index eec9e74..4465bc9 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -6,9 +6,42 @@
+ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
++enum mtk_vendor_attr_edcca_ctrl {
++ MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
++
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
++};
++
++enum mtk_vendor_attr_edcca_dump {
++ MTK_VENDOR_ATTR_EDCCA_DUMP_UNSPEC = 0,
++
++ MTK_VENDOR_ATTR_EDCCA_DUMP_MODE,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
++};
++
+ enum mtk_vendor_attr_mu_ctrl {
+ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch
new file mode 100644
index 0000000..f7596bb
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch
@@ -0,0 +1,30 @@
+From e24d476d4baca1aa3a32ac82ec0f1ea56cedf06c Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Wed, 28 Jun 2023 05:07:43 +0800
+Subject: [PATCH 53/98] wifi: mt76: mt7996: Fix incorrect UWTBL_LEN_IN_DW
+ parameter
+
+The UWTBL length is 16 DW. Correct the len to 16 so that we can
+see full UWTBL when checking wtbl with debugfs.
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ mt7996/mtk_debug.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
+index 368f0bc..9718c2c 100644
+--- a/mt7996/mtk_debug.h
++++ b/mt7996/mtk_debug.h
+@@ -834,7 +834,7 @@ enum cipher_suit {
+ };
+
+ #define LWTBL_LEN_IN_DW 36
+-#define UWTBL_LEN_IN_DW 10
++#define UWTBL_LEN_IN_DW 16
+
+ #define MT_DBG_WTBL_BASE 0x820D8000
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch
new file mode 100644
index 0000000..142193f
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch
@@ -0,0 +1,393 @@
+From 86906513b2597a79c26b72a6a9dc0ecf8b0ce1ed Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 10 Jul 2023 11:47:29 +0800
+Subject: [PATCH 54/98] wifi: mt76: mt7996: add support spatial reuse debug
+ commands
+
+This commit adds the following debug commands in debugfs:
+1. sr_enable: enable/disable spatial reuse feature. Default is on.
+2. sr_enhanced_enable: enable/disable enhanced spatial reuse feature.
+Default is on. This feature is mtk proprietary feature.
+3. sr_stats: Check the Spatial reuse tx statistics.
+4. sr_scene_cond: Check the result of mtk scene detection algorithm. Mtk
+scene detection algorithm in firmware may decide whether current
+environment can SR Tx or not.
+
+To learn more details of these commands, please check:
+https://wiki.mediatek.inc/display/APKB/mt76+Phy+feature+debug+Cheetsheet#mt76PhyfeaturedebugCheetsheet-SpatialReuse
+---
+ mt76_connac_mcu.h | 1 +
+ mt7996/main.c | 6 +++
+ mt7996/mcu.c | 5 ++
+ mt7996/mt7996.h | 6 +++
+ mt7996/mtk_debugfs.c | 82 ++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.c | 111 +++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h | 56 ++++++++++++++++++++++
+ 7 files changed, 267 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 42eb64c..e904ebc 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1031,6 +1031,7 @@ enum {
+ MCU_UNI_EVENT_BSS_BEACON_LOSS = 0x0c,
+ MCU_UNI_EVENT_SCAN_DONE = 0x0e,
+ MCU_UNI_EVENT_RDD_REPORT = 0x11,
++ MCU_UNI_EVENT_SR = 0x25,
+ MCU_UNI_EVENT_ROC = 0x27,
+ MCU_UNI_EVENT_TX_DONE = 0x2d,
+ MCU_UNI_EVENT_BF = 0x33,
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d928564..35f8fee 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -6,6 +6,9 @@
+ #include "mt7996.h"
+ #include "mcu.h"
+ #include "mac.h"
++#ifdef CONFIG_MTK_DEBUG
++#include "mtk_mcu.h"
++#endif
+
+ static bool mt7996_dev_running(struct mt7996_dev *dev)
+ {
+@@ -78,6 +81,9 @@ int mt7996_run(struct ieee80211_hw *hw)
+ goto out;
+
+ #ifdef CONFIG_MTK_DEBUG
++ phy->sr_enable = true;
++ phy->enhanced_sr_enable = true;
++
+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
+ !dev->dbg.sku_disable);
+ #else
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 722c435..2dbec1e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -617,6 +617,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ case MCU_UNI_EVENT_RDD_REPORT:
+ mt7996_mcu_rx_radar_detected(dev, skb);
+ break;
++#ifdef CONFIG_MTK_DEBUG
++ case MCU_UNI_EVENT_SR:
++ mt7996_mcu_rx_sr_event(dev, skb);
++ break;
++#endif
+ case MCU_UNI_EVENT_THERMAL:
+ mt7996_mcu_rx_thermal_notify(dev, skb);
+ break;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 8fd29d7..1fac783 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -306,6 +306,10 @@ struct mt7996_phy {
+ spinlock_t amnt_lock;
+ struct mt7996_air_monitor_ctrl amnt_ctrl;
+ #endif
++#ifdef CONFIG_MTK_DEBUG
++ bool sr_enable:1;
++ bool enhanced_sr_enable:1;
++#endif
+ };
+
+ struct mt7996_dev {
+@@ -763,6 +767,8 @@ enum edcca_bw_id {
+
+ #ifdef CONFIG_MTK_DEBUG
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
++int mt7996_mcu_set_sr_enable(struct mt7996_phy *phy, u8 action, u64 val, bool set);
++void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 82b2785..f56ad88 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2589,6 +2589,83 @@ static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
+ return 0;
+ }
+
++static int
++mt7996_sr_enable_get(void *data, u64 *val)
++{
++ struct mt7996_phy *phy = data;
++
++ *val = phy->sr_enable;
++
++ return 0;
++}
++
++static int
++mt7996_sr_enable_set(void *data, u64 val)
++{
++ struct mt7996_phy *phy = data;
++ int ret;
++
++ if (!!val == phy->sr_enable)
++ return 0;
++
++ ret = mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_CFG_SR_ENABLE, val, true);
++ if (ret)
++ return ret;
++
++ return mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_CFG_SR_ENABLE, 0, false);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_sr_enable, mt7996_sr_enable_get,
++ mt7996_sr_enable_set, "%lld\n");
++static int
++mt7996_sr_enhanced_enable_get(void *data, u64 *val)
++{
++ struct mt7996_phy *phy = data;
++
++ *val = phy->enhanced_sr_enable;
++
++ return 0;
++}
++
++static int
++mt7996_sr_enhanced_enable_set(void *data, u64 val)
++{
++ struct mt7996_phy *phy = data;
++ int ret;
++
++ if (!!val == phy->enhanced_sr_enable)
++ return 0;
++
++ ret = mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_HW_ENHANCE_SR_ENABLE, val, true);
++ if (ret)
++ return ret;
++
++ return mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_HW_ENHANCE_SR_ENABLE, 0, false);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_sr_enhanced_enable, mt7996_sr_enhanced_enable_get,
++ mt7996_sr_enhanced_enable_set, "%lld\n");
++
++static int
++mt7996_sr_stats_show(struct seq_file *file, void *data)
++{
++ struct mt7996_phy *phy = file->private;
++
++ mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_HW_IND, 0, false);
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(mt7996_sr_stats);
++
++static int
++mt7996_sr_scene_cond_show(struct seq_file *file, void *data)
++{
++ struct mt7996_phy *phy = file->private;
++
++ mt7996_mcu_set_sr_enable(phy, UNI_CMD_SR_SW_SD, 0, false);
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(mt7996_sr_scene_cond);
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ struct mt7996_dev *dev = phy->dev;
+@@ -2642,6 +2719,11 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+
+ debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable);
+
++ debugfs_create_file("sr_enable", 0600, dir, phy, &fops_sr_enable);
++ debugfs_create_file("sr_enhanced_enable", 0600, dir, phy, &fops_sr_enhanced_enable);
++ debugfs_create_file("sr_stats", 0400, dir, phy, &mt7996_sr_stats_fops);
++ debugfs_create_file("sr_scene_cond", 0400, dir, phy, &mt7996_sr_scene_cond_fops);
++
+ return 0;
+ }
+
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index 048c534..3256de7 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -124,4 +124,115 @@ int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set)
+ return 0;
+ }
+
++int mt7996_mcu_set_sr_enable(struct mt7996_phy *phy, u8 action, u64 val, bool set)
++{
++ struct {
++ u8 band_idx;
++ u8 _rsv[3];
++
++ __le16 tag;
++ __le16 len;
++
++ __le32 val;
++
++ } __packed req = {
++ .band_idx = phy->mt76->band_idx,
++
++ .tag = cpu_to_le16(action),
++ .len = cpu_to_le16(sizeof(req) - 4),
++
++ .val = cpu_to_le32((u32) val),
++ };
++
++ if (set)
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SR), &req,
++ sizeof(req), false);
++ else
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD_QUERY(SR), &req,
++ sizeof(req), false);
++}
++
++void mt7996_mcu_rx_sr_swsd(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++#define SR_SCENE_DETECTION_TIMER_PERIOD_MS 500
++ struct mt7996_mcu_sr_swsd_event *event;
++ static const char * const rules[] = {"1 - NO CONNECTED", "2 - NO CONGESTION",
++ "3 - NO INTERFERENCE", "4 - SR ON"};
++ u8 idx;
++
++ event = (struct mt7996_mcu_sr_swsd_event *)skb->data;
++ idx = event->basic.band_idx;
++
++ dev_info(dev->mt76.dev, "Band index = %u\n", le16_to_cpu(event->basic.band_idx));
++ dev_info(dev->mt76.dev, "Hit Rule = %s\n", rules[event->tlv[idx].rule]);
++ dev_info(dev->mt76.dev, "Timer Period = %d(us)\n"
++ "Congestion Ratio = %d.%1d%%\n",
++ SR_SCENE_DETECTION_TIMER_PERIOD_MS * 1000,
++ le32_to_cpu(event->tlv[idx].total_airtime_ratio) / 10,
++ le32_to_cpu(event->tlv[idx].total_airtime_ratio) % 10);
++ dev_info(dev->mt76.dev,
++ "Total Airtime = %d(us)\n"
++ "ChBusy = %d\n"
++ "SrTx = %d\n"
++ "OBSS = %d\n"
++ "MyTx = %d\n"
++ "MyRx = %d\n"
++ "Interference Ratio = %d.%1d%%\n",
++ le32_to_cpu(event->tlv[idx].total_airtime),
++ le32_to_cpu(event->tlv[idx].channel_busy_time),
++ le32_to_cpu(event->tlv[idx].sr_tx_airtime),
++ le32_to_cpu(event->tlv[idx].obss_airtime),
++ le32_to_cpu(event->tlv[idx].my_tx_airtime),
++ le32_to_cpu(event->tlv[idx].my_rx_airtime),
++ le32_to_cpu(event->tlv[idx].obss_airtime_ratio) / 10,
++ le32_to_cpu(event->tlv[idx].obss_airtime_ratio) % 10);
++}
++
++void mt7996_mcu_rx_sr_hw_indicator(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++ struct mt7996_mcu_sr_hw_ind_event *event;
++
++ event = (struct mt7996_mcu_sr_hw_ind_event *)skb->data;
++
++ dev_info(dev->mt76.dev, "Inter PPDU Count = %u\n",
++ le16_to_cpu(event->inter_bss_ppdu_cnt));
++ dev_info(dev->mt76.dev, "SR Valid Count = %u\n",
++ le16_to_cpu(event->non_srg_valid_cnt));
++ dev_info(dev->mt76.dev, "SR Tx Count = %u\n",
++ le32_to_cpu(event->sr_ampdu_mpdu_cnt));
++ dev_info(dev->mt76.dev, "SR Tx Acked Count = %u\n",
++ le32_to_cpu(event->sr_ampdu_mpdu_acked_cnt));
++}
++
++void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++ struct mt76_phy *mphy = &dev->mt76.phy;
++ struct mt7996_phy *phy;
++ struct mt7996_mcu_sr_common_event *event;
++
++ event = (struct mt7996_mcu_sr_common_event *)skb->data;
++ mphy = dev->mt76.phys[event->basic.band_idx];
++ if (!mphy)
++ return;
++
++ phy = (struct mt7996_phy *)mphy->priv;
++
++ switch (le16_to_cpu(event->basic.tag)) {
++ case UNI_EVENT_SR_CFG_SR_ENABLE:
++ phy->sr_enable = le32_to_cpu(event->value) ? true : false;
++ break;
++ case UNI_EVENT_SR_HW_ESR_ENABLE:
++ phy->enhanced_sr_enable = le32_to_cpu(event->value) ? true : false;
++ break;
++ case UNI_EVENT_SR_SW_SD:
++ mt7996_mcu_rx_sr_swsd(dev, skb);
++ break;
++ case UNI_EVENT_SR_HW_IND:
++ mt7996_mcu_rx_sr_hw_indicator(dev, skb);
++ break;
++ default:
++ dev_info(dev->mt76.dev, "Unknown SR event tag %d\n",
++ le16_to_cpu(event->basic.tag));
++ }
++}
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index 9c0db87..a5bdb88 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -104,6 +104,62 @@ enum {
+ EDCCA_JAPAN = 3
+ };
+
++enum {
++ UNI_EVENT_SR_CFG_SR_ENABLE = 0x1,
++ UNI_EVENT_SR_SW_SD = 0x83,
++ UNI_EVENT_SR_HW_IND = 0xC9,
++ UNI_EVENT_SR_HW_ESR_ENABLE = 0xD8,
++};
++enum {
++ UNI_CMD_SR_CFG_SR_ENABLE = 0x1,
++ UNI_CMD_SR_SW_SD = 0x84,
++ UNI_CMD_SR_HW_IND = 0xCB,
++ UNI_CMD_SR_HW_ENHANCE_SR_ENABLE = 0xDA,
++};
++
++struct mt7996_mcu_sr_basic_event {
++ struct mt7996_mcu_rxd rxd;
++
++ u8 band_idx;
++ u8 _rsv[3];
++
++ __le16 tag;
++ __le16 len;
++};
++
++struct sr_sd_tlv {
++ u8 _rsv[16];
++ __le32 sr_tx_airtime;
++ __le32 obss_airtime;
++ __le32 my_tx_airtime;
++ __le32 my_rx_airtime;
++ __le32 channel_busy_time;
++ __le32 total_airtime;
++ __le32 total_airtime_ratio;
++ __le32 obss_airtime_ratio;
++ u8 rule;
++ u8 _rsv2[59];
++} __packed;
++
++struct mt7996_mcu_sr_swsd_event {
++ struct mt7996_mcu_sr_basic_event basic;
++ struct sr_sd_tlv tlv[3];
++} __packed;
++
++struct mt7996_mcu_sr_common_event {
++ struct mt7996_mcu_sr_basic_event basic;
++ __le32 value;
++};
++
++struct mt7996_mcu_sr_hw_ind_event {
++ struct mt7996_mcu_sr_basic_event basic;
++ __le16 non_srg_valid_cnt;
++ u8 _rsv[4];
++ __le16 inter_bss_ppdu_cnt;
++ u8 _rsv2[4];
++ __le32 sr_ampdu_mpdu_cnt;
++ __le32 sr_ampdu_mpdu_acked_cnt;
++};
+ #endif
+
+ #endif
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
new file mode 100644
index 0000000..ac60aa8
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
@@ -0,0 +1,25 @@
+From d7337c25e774ed96fc8f6d1390321bfc2dcac545 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Tue, 1 Aug 2023 16:02:28 +0800
+Subject: [PATCH 55/98] wifi: mt76: mt7996: Establish BA in VO queue
+
+---
+ mt7996/mac.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 37cc94e..b24f237 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1017,8 +1017,6 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
+ return;
+
+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+- if (tid >= 6) /* skip VO queue */
+- return;
+
+ if (is_8023)
+ fc = IEEE80211_FTYPE_DATA |
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch
new file mode 100644
index 0000000..9fbc586
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch
@@ -0,0 +1,144 @@
+From b69722554a27e8c13612f62c9b9cf8651a30bd8f Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 5 Jul 2023 10:00:17 +0800
+Subject: [PATCH 56/98] wifi: mt76: mt7996: add eagle iFEM HWITS ZWDFS SW
+ workaround
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/main.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++---
+ mt7996/mcu.c | 6 +++--
+ mt7996/mt7996.h | 1 +
+ 3 files changed, 60 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 35f8fee..d27275a 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1413,6 +1413,54 @@ mt7996_twt_teardown_request(struct ieee80211_hw *hw,
+ mutex_unlock(&dev->mt76.mutex);
+ }
+
++static void
++mt7996_background_radar_handle_7975_ifem(struct ieee80211_hw *hw,
++ struct cfg80211_chan_def *user_chandef,
++ struct cfg80211_chan_def *fw_chandef)
++{
++ struct mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct mt7996_dev *dev = phy->dev;
++ struct cfg80211_chan_def *c = user_chandef;
++ bool is_ifem_adie, expand = false;
++ u32 origin_control;
++
++ if (is_mt7996(&dev->mt76))
++ is_ifem_adie = !!(mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) % 2);
++ else
++ is_ifem_adie = (mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB_7992) == 1);
++
++ if (!user_chandef || !is_ifem_adie)
++ goto out;
++
++ if (user_chandef->width == NL80211_CHAN_WIDTH_160) {
++ origin_control = user_chandef->chan->center_freq;
++ if (dev->bg_nxt_freq)
++ goto out;
++
++ if (user_chandef->chan->flags & IEEE80211_CHAN_RADAR)
++ dev->bg_nxt_freq = origin_control;
++ else
++ c = fw_chandef;
++
++ c->chan = ieee80211_get_channel(hw->wiphy, origin_control + 80);
++ } else {
++ if (!dev->bg_nxt_freq)
++ goto out;
++
++ c->chan = ieee80211_get_channel(hw->wiphy, dev->bg_nxt_freq);
++ dev->bg_nxt_freq = 0;
++ expand = true;
++ }
++ c->width = NL80211_CHAN_WIDTH_80;
++ c->center_freq1 = c->chan->center_freq + 30;
++
++ if (c == user_chandef)
++ cfg80211_background_radar_update_channel(hw->wiphy, c, expand);
++ return;
++out:
++ dev->bg_nxt_freq = 0;
++}
++
+ static int
+ mt7996_set_radar_background(struct ieee80211_hw *hw,
+ struct cfg80211_chan_def *chandef)
+@@ -1421,6 +1469,7 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
+ struct mt7996_dev *dev = phy->dev;
+ int ret = -EINVAL;
+ bool running;
++ struct cfg80211_chan_def ifem_chandef = {};
+
+ mutex_lock(&dev->mt76.mutex);
+
+@@ -1433,13 +1482,14 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
+ goto out;
+ }
+
++ mt7996_background_radar_handle_7975_ifem(hw, chandef, &ifem_chandef);
++
+ /* rdd2 already configured on a radar channel */
+ running = dev->rdd2_phy &&
+ cfg80211_chandef_valid(&dev->rdd2_chandef) &&
+ !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR);
+
+- if (!chandef || running ||
+- !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
++ if (!chandef || running) {
+ ret = mt7996_mcu_rdd_background_enable(phy, NULL);
+ if (ret)
+ goto out;
+@@ -1448,7 +1498,9 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
+ goto update_phy;
+ }
+
+- ret = mt7996_mcu_rdd_background_enable(phy, chandef);
++ ret = mt7996_mcu_rdd_background_enable(phy,
++ ifem_chandef.chan ?
++ &ifem_chandef : chandef);
+ if (ret)
+ goto out;
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 2dbec1e..a4f3ed9 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -350,12 +350,14 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
+ if (!mphy)
+ return;
+
+- if (r->band_idx == MT_RX_SEL2)
++ if (r->band_idx == MT_RX_SEL2) {
++ dev->bg_nxt_freq = 0;
+ cfg80211_background_radar_event(mphy->hw->wiphy,
+ &dev->rdd2_chandef,
+ GFP_ATOMIC);
+- else
++ } else {
+ ieee80211_radar_detected(mphy->hw);
++ }
+ dev->hw_pattern++;
+ }
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 1fac783..413fbf7 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -392,6 +392,7 @@ struct mt7996_dev {
+ bool testmode_enable;
+ bool bin_file_mode;
+ u8 eeprom_mode;
++ u32 bg_nxt_freq;
+
+ bool ibf;
+ u8 fw_debug_wm;
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch
new file mode 100644
index 0000000..63afb2c
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch
@@ -0,0 +1,46 @@
+From fd96728a963faf55b7daba46a78aa25ab0c5f147 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Sat, 12 Aug 2023 04:17:22 +0800
+Subject: [PATCH 57/98] wifi: mt76: mt7996: report tx and rx byte to tpt_led
+
+---
+ mt7996/mcu.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a4f3ed9..3a960d1 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -531,6 +531,8 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ u8 ac;
+ u16 wlan_idx;
+ struct mt76_wcid *wcid;
++ struct mt76_phy *mphy;
++ u32 tx_bytes, rx_bytes;
+
+ switch (le16_to_cpu(res->tag)) {
+ case UNI_ALL_STA_TXRX_RATE:
+@@ -550,11 +552,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ if (!wcid)
+ break;
+
++ mphy = mt76_dev_phy(&dev->mt76, wcid->phy_idx);
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+- wcid->stats.tx_bytes +=
+- le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
+- wcid->stats.rx_bytes +=
+- le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
++ tx_bytes = le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
++ rx_bytes = le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
++
++ wcid->stats.tx_bytes += tx_bytes;
++ wcid->stats.rx_bytes += rx_bytes;
++
++ ieee80211_tpt_led_trig_tx(mphy->hw, tx_bytes);
++ ieee80211_tpt_led_trig_rx(mphy->hw, rx_bytes);
+ }
+ break;
+ case UNI_ALL_STA_TXRX_MSDU_COUNT:
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1025-wifi-mt76-mt7996-support-dup-wtbl.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1025-wifi-mt76-mt7996-support-dup-wtbl.patch
new file mode 100644
index 0000000..12cdca3
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1025-wifi-mt76-mt7996-support-dup-wtbl.patch
@@ -0,0 +1,72 @@
+From a0baa183c16552ec874141c62ce3c6346d24c684 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 21 Sep 2023 00:52:46 +0800
+Subject: [PATCH 58/98] wifi: mt76: mt7996: support dup wtbl
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I14ba41ace8341c23c1cfb6e9c4fbb2d5e93a5714
+---
+ mt7996/init.c | 1 +
+ mt7996/mt7996.h | 1 +
+ mt7996/mtk_mcu.c | 23 +++++++++++++++++++++++
+ 3 files changed, 25 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index ad93927..4503482 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -660,6 +660,7 @@ static void mt7996_init_work(struct work_struct *work)
+ mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
+ mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
+ mt7996_txbf_init(dev);
++ mt7996_mcu_set_dup_wtbl(dev);
+ }
+
+ void mt7996_wfsys_reset(struct mt7996_dev *dev)
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 413fbf7..766de3f 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -770,6 +770,7 @@ enum edcca_bw_id {
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
+ int mt7996_mcu_set_sr_enable(struct mt7996_phy *phy, u8 action, u64 val, bool set);
+ void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb);
++int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
+ #endif
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index 3256de7..149694c 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -235,4 +235,27 @@ void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ le16_to_cpu(event->basic.tag));
+ }
+ }
++
++int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev)
++{
++#define CHIP_CONFIG_DUP_WTBL 4
++#define DUP_WTBL_NUM 80
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++ __le16 base;
++ __le16 num;
++ u8 _rsv2[4];
++ } __packed req = {
++ .tag = cpu_to_le16(CHIP_CONFIG_DUP_WTBL),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .base = cpu_to_le16(MT7996_WTBL_STA - DUP_WTBL_NUM + 1),
++ .num = cpu_to_le16(DUP_WTBL_NUM),
++ };
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(CHIP_CONFIG), &req,
++ sizeof(req), true);
++}
+ #endif
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
new file mode 100644
index 0000000..354e553
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
@@ -0,0 +1,143 @@
+From b5d139f32d6f4f6476b82d59af7a96a1f57858a9 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
+Date: Fri, 22 Sep 2023 09:54:49 +0800
+Subject: [PATCH 59/98] wifi: mt76: mt7996: add ibf control vendor cmd
+
+Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+---
+ mt7996/vendor.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 23 +++++++++++++++++
+ 2 files changed, 88 insertions(+)
+
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 9f333d0..dae3260 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -60,6 +60,11 @@ edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL] = { .type = NLA_U8 },
+ };
+
++static const struct nla_policy
++ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
++ [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ u8 idx;
+ u8 addr[ETH_ALEN];
+@@ -556,6 +561,54 @@ mt7996_vendor_edcca_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ return EDCCA_MAX_BW_NUM;
+ }
+
++static int mt7996_vendor_ibf_ctrl(struct wiphy *wiphy,
++ struct wireless_dev *wdev,
++ const void *data,
++ int data_len)
++{
++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++ struct mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct mt7996_dev *dev = phy->dev;
++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_IBF_CTRL];
++ int err;
++ u8 val;
++
++ err = nla_parse(tb, MTK_VENDOR_ATTR_IBF_CTRL_MAX, data, data_len,
++ ibf_ctrl_policy, NULL);
++ if (err)
++ return err;
++
++ if (tb[MTK_VENDOR_ATTR_IBF_CTRL_ENABLE]) {
++ val = nla_get_u8(tb[MTK_VENDOR_ATTR_IBF_CTRL_ENABLE]);
++
++ dev->ibf = !!val;
++
++ err = mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++static int
++mt7996_vendor_ibf_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 mt7996_phy *phy = mt7996_hw_phy(hw);
++ struct mt7996_dev *dev = phy->dev;
++
++ if (*storage == 1)
++ return -ENOENT;
++ *storage = 1;
++
++ if (nla_put_u8(skb, MTK_VENDOR_ATTR_IBF_DUMP_ENABLE, dev->ibf))
++ return -ENOMEM;
++
++ return 1;
++}
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ {
+ .info = {
+@@ -604,6 +657,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ .policy = edcca_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
+ },
++ {
++ .info = {
++ .vendor_id = MTK_NL80211_VENDOR_ID,
++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL,
++ },
++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++ WIPHY_VENDOR_CMD_NEED_RUNNING,
++ .doit = mt7996_vendor_ibf_ctrl,
++ .dumpit = mt7996_vendor_ibf_ctrl_dump,
++ .policy = ibf_ctrl_policy,
++ .maxattr = MTK_VENDOR_ATTR_IBF_CTRL_MAX,
++ },
+ };
+
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 4465bc9..49f46f2 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -7,6 +7,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
++ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
+ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+@@ -102,4 +103,26 @@ enum mtk_vendor_attr_bss_color_ctrl {
+ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
+ };
+
++enum mtk_vendor_attr_ibf_ctrl {
++ MTK_VENDOR_ATTR_IBF_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_IBF_CTRL_ENABLE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_IBF_CTRL,
++ MTK_VENDOR_ATTR_IBF_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_IBF_CTRL - 1
++};
++
++enum mtk_vendor_attr_ibf_dump {
++ MTK_VENDOR_ATTR_IBF_DUMP_UNSPEC,
++
++ MTK_VENDOR_ATTR_IBF_DUMP_ENABLE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_IBF_DUMP,
++ MTK_VENDOR_ATTR_IBF_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
++};
++
+ #endif
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch
new file mode 100644
index 0000000..a555c23
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch
@@ -0,0 +1,120 @@
+From 4f5af38dbe7866b635428ebe80df29ab96bd660e Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 26 May 2023 14:41:27 +0800
+Subject: [PATCH 60/98] wifi: mt76: mt7996: add kite fwdl support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac_mcu.c | 3 ++-
+ mt7996/mcu.c | 26 +++++++++++++++++++++-----
+ mt7996/mt7996.h | 6 ++++++
+ mt7996/pci.c | 4 ++++
+ 4 files changed, 33 insertions(+), 6 deletions(-)
+
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index 214a526..43e8ce0 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -68,7 +68,8 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
+ if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
+ (is_mt7921(dev) && addr == 0x900000) ||
+ (is_mt7925(dev) && addr == 0x900000) ||
+- (is_mt7996(dev) && addr == 0x900000))
++ (is_mt7996(dev) && addr == 0x900000) ||
++ (is_mt7992(dev) && addr == 0x900000))
+ cmd = MCU_CMD(PATCH_START_REQ);
+ else
+ cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 3a960d1..255d0ba 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -11,6 +11,22 @@
+ #include "mac.h"
+ #include "eeprom.h"
+
++#define fw_name(_dev, name, ...) ({ \
++ char *_fw; \
++ switch (mt76_chip(&(_dev)->mt76)) { \
++ case 0x7996: \
++ _fw = MT7996_##name; \
++ break; \
++ case 0x7992: \
++ _fw = MT7992_##name; \
++ break; \
++ default: \
++ _fw = MT7996_##name; \
++ break; \
++ } \
++ _fw; \
++})
++
+ struct mt7996_patch_hdr {
+ char build_date[16];
+ char platform[4];
+@@ -2598,7 +2614,7 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
+ return -EAGAIN;
+ }
+
+- ret = request_firmware(&fw, MT7996_ROM_PATCH, dev->mt76.dev);
++ ret = request_firmware(&fw, fw_name(dev, ROM_PATCH), dev->mt76.dev);
+ if (ret)
+ goto out;
+
+@@ -2767,20 +2783,20 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+ int ret;
+
+ if (dev->testmode_enable)
+- ret = __mt7996_load_ram(dev, "WM_TM", MT7996_FIRMWARE_WM_TM,
++ ret = __mt7996_load_ram(dev, "WM_TM", fw_name(dev, FIRMWARE_WM_TM),
+ MT7996_RAM_TYPE_WM_TM);
+ else
+- ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
++ ret = __mt7996_load_ram(dev, "WM", fw_name(dev, FIRMWARE_WM),
+ MT7996_RAM_TYPE_WM);
+ if (ret)
+ return ret;
+
+- ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP,
++ ret = __mt7996_load_ram(dev, "DSP", fw_name(dev, FIRMWARE_DSP),
+ MT7996_RAM_TYPE_DSP);
+ if (ret)
+ return ret;
+
+- return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA,
++ return __mt7996_load_ram(dev, "WA", fw_name(dev, FIRMWARE_WA),
+ MT7996_RAM_TYPE_WA);
+ }
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 766de3f..eb192eb 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -35,6 +35,12 @@
+ #define MT7996_FIRMWARE_WM_TM "mediatek/mt7996/mt7996_wm_tm.bin"
+ #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
+
++#define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin"
++#define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin"
++#define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin"
++#define MT7992_FIRMWARE_WM_TM "mediatek/mt7996/mt7992_wm_tm.bin"
++#define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
++
+ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
+ #define MT7996_EEPROM_DEFAULT_404 "mediatek/mt7996/mt7996_eeprom_dual_404.bin"
+ #define MT7996_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7996_eeprom_tm.bin"
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index e8edf77..2bb707d 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -263,3 +263,7 @@ MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
+ MODULE_FIRMWARE(MT7996_ROM_PATCH);
++MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
++MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
++MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
++MODULE_FIRMWARE(MT7992_ROM_PATCH);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch
new file mode 100644
index 0000000..3556945
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch
@@ -0,0 +1,146 @@
+From dcace898314b1d369b61a0c4f7f9e325f04784dc Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 26 May 2023 14:44:04 +0800
+Subject: [PATCH 61/98] wifi: mt76: mt7996: add kite eeprom load support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 33 ++++++++++++++++++++++-----------
+ mt7996/mcu.c | 2 +-
+ mt7996/mt7996.h | 10 ++++++++++
+ 3 files changed, 33 insertions(+), 12 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 56605de..6605853 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -53,9 +53,12 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ u8 *eeprom = dev->mt76.eeprom.data;
+ u16 val = get_unaligned_le16(eeprom);
+
++#define CHECK_EEPROM_ERR(match) (match ? 0 : -EINVAL)
+ switch (val) {
+ case 0x7990:
+- return 0;
++ return CHECK_EEPROM_ERR(is_mt7996(&dev->mt76));
++ case 0x7992:
++ return CHECK_EEPROM_ERR(is_mt7992(&dev->mt76));
+ default:
+ return -EINVAL;
+ }
+@@ -66,13 +69,20 @@ const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ if (dev->bin_file_mode)
+ return dev->mt76.bin_file_name;
+
+- /* reserve for future variants */
+- if (dev->testmode_enable)
+- return MT7996_EEPROM_DEFAULT_TM;
+- else if (dev->chip_sku == MT7996_SKU_404)
+- return MT7996_EEPROM_DEFAULT_404;
+- else
++ switch (mt76_chip(&dev->mt76)) {
++ case 0x7990:
++ if (dev->testmode_enable)
++ return MT7996_EEPROM_DEFAULT_TM;
++ else if (dev->chip_sku == MT7996_SKU_404)
++ return MT7996_EEPROM_DEFAULT_404;
++ else
++ return MT7996_EEPROM_DEFAULT;
++ case 0x7992:
++ return dev->testmode_enable ?
++ MT7992_EEPROM_DEFAULT_TM : MT7992_EEPROM_DEFAULT;
++ default:
+ return MT7996_EEPROM_DEFAULT;
++ }
+ }
+
+ int
+@@ -125,7 +135,7 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+ goto out;
+ }
+
+- memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);
++ memcpy(eeprom, fw->data, mt7996_eeprom_size(dev));
+ dev->flash_mode = true;
+
+ out:
+@@ -141,7 +151,7 @@ static int mt7996_eeprom_load_flash(struct mt7996_dev *dev)
+ /* return > 0 for load success, return 0 for load failed, return < 0 for non memory */
+ dev->bin_file_mode = mt76_check_bin_file_mode(&dev->mt76);
+ if (dev->bin_file_mode) {
+- dev->mt76.eeprom.size = MT7996_EEPROM_SIZE;
++ dev->mt76.eeprom.size = mt7996_eeprom_size(dev);
+ dev->mt76.eeprom.data = devm_kzalloc(dev->mt76.dev, dev->mt76.eeprom.size,
+ GFP_KERNEL);
+ if (!dev->mt76.eeprom.data)
+@@ -153,7 +163,7 @@ static int mt7996_eeprom_load_flash(struct mt7996_dev *dev)
+ if (mt7996_check_eeprom(dev))
+ return 0;
+ } else {
+- ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
++ ret = mt76_eeprom_init(&dev->mt76, mt7996_eeprom_size(dev));
+ }
+
+ return ret;
+@@ -186,6 +196,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+ {
+ int ret;
+ u8 free_block_num;
++ u16 eeprom_size = mt7996_eeprom_size(dev);
+ u32 block_num, i;
+ u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
+
+@@ -200,7 +211,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+ return -EINVAL;
+
+ /* read eeprom data from efuse */
+- block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
++ block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);
+ for (i = 0; i < block_num; i++) {
+ ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size);
+ if (ret < 0)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 255d0ba..e9088ba 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3425,7 +3425,7 @@ static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
+ .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
+ .buffer_mode = EE_MODE_BUFFER
+ };
+- u16 eeprom_size = MT7996_EEPROM_SIZE;
++ u16 eeprom_size = mt7996_eeprom_size(dev);
+ u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);
+ u8 *eep = (u8 *)dev->mt76.eeprom.data;
+ int eep_len, i;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index eb192eb..433d886 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -44,7 +44,12 @@
+ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
+ #define MT7996_EEPROM_DEFAULT_404 "mediatek/mt7996/mt7996_eeprom_dual_404.bin"
+ #define MT7996_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7996_eeprom_tm.bin"
++#define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin"
++#define MT7992_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7992_eeprom_tm.bin"
++
+ #define MT7996_EEPROM_SIZE 7680
++#define MT7992_EEPROM_SIZE 7680
++
+ #define MT7996_EEPROM_BLOCK_SIZE 16
+ #define MT7996_TOKEN_SIZE 16384
+ #define MT7996_HW_TOKEN_SIZE 8192
+@@ -643,6 +648,11 @@ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
+
++static inline u16 mt7996_eeprom_size(struct mt7996_dev *dev)
++{
++ return is_mt7996(&dev->mt76) ? MT7996_EEPROM_SIZE : MT7992_EEPROM_SIZE;
++}
++
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+ return min(MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support),
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch
new file mode 100644
index 0000000..8b8119a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch
@@ -0,0 +1,128 @@
+From af793eb0cf8e035760bdb595ae96e7d7534df60f Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 21 Jul 2023 10:41:28 +0800
+Subject: [PATCH 62/98] wifi: mt76: mt7996: add kite fw & default bin for
+ different sku variants
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 10 ++++++++--
+ mt7996/mcu.c | 7 ++++++-
+ mt7996/mt7996.h | 25 ++++++++++++++++++++++++-
+ mt7996/regs.h | 2 ++
+ 4 files changed, 40 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 6605853..6eebbb3 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -78,8 +78,14 @@ const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ else
+ return MT7996_EEPROM_DEFAULT;
+ case 0x7992:
+- return dev->testmode_enable ?
+- MT7992_EEPROM_DEFAULT_TM : MT7992_EEPROM_DEFAULT;
++ if (dev->testmode_enable)
++ return MT7992_EEPROM_DEFAULT_TM;
++ else if (dev->chip_sku == MT7992_SKU_23)
++ return MT7992_EEPROM_DEFAULT_23;
++ else if (dev->chip_sku == MT7992_SKU_24)
++ return MT7992_EEPROM_DEFAULT_24;
++ else
++ return MT7992_EEPROM_DEFAULT;
+ default:
+ return MT7996_EEPROM_DEFAULT;
+ }
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index e9088ba..b8d26ec 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -18,7 +18,12 @@
+ _fw = MT7996_##name; \
+ break; \
+ case 0x7992: \
+- _fw = MT7992_##name; \
++ if ((_dev)->chip_sku == MT7992_SKU_23) \
++ _fw = MT7992_##name##_23; \
++ else if ((_dev)->chip_sku == MT7992_SKU_24) \
++ _fw = MT7992_##name##_24; \
++ else \
++ _fw = MT7992_##name; \
+ break; \
+ default: \
+ _fw = MT7996_##name; \
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 433d886..6775360 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -41,11 +41,25 @@
+ #define MT7992_FIRMWARE_WM_TM "mediatek/mt7996/mt7992_wm_tm.bin"
+ #define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
+
++#define MT7992_FIRMWARE_WA_24 "mediatek/mt7996/mt7992_wa_24.bin"
++#define MT7992_FIRMWARE_WM_24 "mediatek/mt7996/mt7992_wm_24.bin"
++#define MT7992_FIRMWARE_DSP_24 "mediatek/mt7996/mt7992_dsp_24.bin"
++#define MT7992_FIRMWARE_WM_TM_24 "mediatek/mt7996/mt7992_wm_tm_24.bin"
++#define MT7992_ROM_PATCH_24 "mediatek/mt7996/mt7992_rom_patch_24.bin"
++
++#define MT7992_FIRMWARE_WA_23 "mediatek/mt7996/mt7992_wa_23.bin"
++#define MT7992_FIRMWARE_WM_23 "mediatek/mt7996/mt7992_wm_23.bin"
++#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
++#define MT7992_FIRMWARE_WM_TM_23 "mediatek/mt7996/mt7992_wm_tm_23.bin"
++#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
++
+ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
+ #define MT7996_EEPROM_DEFAULT_404 "mediatek/mt7996/mt7996_eeprom_dual_404.bin"
+ #define MT7996_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7996_eeprom_tm.bin"
+ #define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin"
+ #define MT7992_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7992_eeprom_tm.bin"
++#define MT7992_EEPROM_DEFAULT_24 "mediatek/mt7996/mt7992_eeprom_24.bin"
++#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"
+
+ #define MT7996_EEPROM_SIZE 7680
+ #define MT7992_EEPROM_SIZE 7680
+@@ -103,6 +117,12 @@ enum mt7996_sku_type {
+ MT7996_SKU_444,
+ };
+
++enum mt7992_sku_type {
++ MT7992_SKU_23,
++ MT7992_SKU_24,
++ MT7992_SKU_44,
++};
++
+ enum mt7996_ram_type {
+ MT7996_RAM_TYPE_WM,
+ MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
+@@ -510,11 +530,14 @@ mt7996_get_chip_sku(struct mt7996_dev *dev)
+ {
+ u32 val = mt76_rr(dev, MT_PAD_GPIO);
+
+- /* reserve for future variants */
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7990:
+ dev->chip_sku = FIELD_GET(MT_PAD_GPIO_ADIE_COMB, val) <= 1;
+ break;
++ case 0x7992:
++ dev->chip_sku = !!FIELD_GET(MT_PAD_GPIO_ADIE_COMB_7992, val) +
++ !FIELD_GET(MT_PAD_GPIO_ADIE_NUM_7992, val);
++ break;
+ default:
+ return -EINVAL;
+ }
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 565022a..d305c25 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -651,6 +651,8 @@ enum offs_rev {
+
+ #define MT_PAD_GPIO 0x700056f0
+ #define MT_PAD_GPIO_ADIE_COMB GENMASK(16, 15)
++#define MT_PAD_GPIO_ADIE_COMB_7992 GENMASK(17, 16)
++#define MT_PAD_GPIO_ADIE_NUM_7992 BIT(15)
+
+ #define MT_HW_REV 0x70010204
+ #define MT_WF_SUBSYS_RST 0x70028600
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch
new file mode 100644
index 0000000..3af30bf
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch
@@ -0,0 +1,198 @@
+From ab77df3cc660c0aa0f46060499d8704dc389a2a6 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 24 Jul 2023 16:39:22 +0800
+Subject: [PATCH 63/98] wifi: mt76: mt7996: add wtbl_info support for kite
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mtk_debug.h | 22 +++++++++++++
+ mt7996/mtk_debugfs.c | 74 ++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 93 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
+index 9718c2c..1611345 100644
+--- a/mt7996/mtk_debug.h
++++ b/mt7996/mtk_debug.h
+@@ -1088,6 +1088,17 @@ enum cipher_suit {
+ #define WF_LWTBL_AAD_OM_MASK \
+ 0x00008000 // 15-15
+ #define WF_LWTBL_AAD_OM_SHIFT 15
++/* kite DW2 field bit 13-14 */
++#define WF_LWTBL_DUAL_PTEC_EN_DW 2
++#define WF_LWTBL_DUAL_PTEC_EN_ADDR 8
++#define WF_LWTBL_DUAL_PTEC_EN_MASK \
++ 0x00002000 // 13-13
++#define WF_LWTBL_DUAL_PTEC_EN_SHIFT 13
++#define WF_LWTBL_DUAL_CTS_CAP_DW 2
++#define WF_LWTBL_DUAL_CTS_CAP_ADDR 8
++#define WF_LWTBL_DUAL_CTS_CAP_MASK \
++ 0x00004000 // 14-14
++#define WF_LWTBL_DUAL_CTS_CAP_SHIFT 14
+ #define WF_LWTBL_CIPHER_SUIT_PGTK_DW 2
+ #define WF_LWTBL_CIPHER_SUIT_PGTK_ADDR 8
+ #define WF_LWTBL_CIPHER_SUIT_PGTK_MASK \
+@@ -1305,6 +1316,8 @@ enum cipher_suit {
+ #define WF_LWTBL_AF_ADDR 20
+ #define WF_LWTBL_AF_MASK \
+ 0x00000007 // 2- 0
++#define WF_LWTBL_AF_MASK_7992 \
++ 0x0000000f // 3- 0
+ #define WF_LWTBL_AF_SHIFT 0
+ #define WF_LWTBL_AF_HE_DW 5
+ #define WF_LWTBL_AF_HE_ADDR 20
+@@ -1565,16 +1578,25 @@ enum cipher_suit {
+ #define WF_LWTBL_PRITX_SW_MODE_MASK \
+ 0x00008000 // 15-15
+ #define WF_LWTBL_PRITX_SW_MODE_SHIFT 15
++#define WF_LWTBL_PRITX_SW_MODE_MASK_7992 \
++ 0x00004000 // 14-14
++#define WF_LWTBL_PRITX_SW_MODE_SHIFT_7992 14
+ #define WF_LWTBL_PRITX_ERSU_DW 9
+ #define WF_LWTBL_PRITX_ERSU_ADDR 36
+ #define WF_LWTBL_PRITX_ERSU_MASK \
+ 0x00010000 // 16-16
+ #define WF_LWTBL_PRITX_ERSU_SHIFT 16
++#define WF_LWTBL_PRITX_ERSU_MASK_7992 \
++ 0x00008000 // 15-15
++#define WF_LWTBL_PRITX_ERSU_SHIFT_7992 15
+ #define WF_LWTBL_PRITX_PLR_DW 9
+ #define WF_LWTBL_PRITX_PLR_ADDR 36
+ #define WF_LWTBL_PRITX_PLR_MASK \
+ 0x00020000 // 17-17
+ #define WF_LWTBL_PRITX_PLR_SHIFT 17
++#define WF_LWTBL_PRITX_PLR_MASK_7992 \
++ 0x00030000 // 17-16
++#define WF_LWTBL_PRITX_PLR_SHIFT_7992 16
+ #define WF_LWTBL_PRITX_DCM_DW 9
+ #define WF_LWTBL_PRITX_DCM_ADDR 36
+ #define WF_LWTBL_PRITX_DCM_MASK \
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index f56ad88..ce48664 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -1011,7 +1011,8 @@ static void parse_fmac_lwtbl_dw0_1(struct seq_file *s, u8 *lwtbl)
+ }
+ }
+
+-static const struct berse_wtbl_parse WTBL_LMAC_DW2[] = {
++static const struct berse_wtbl_parse *WTBL_LMAC_DW2;
++static const struct berse_wtbl_parse WTBL_LMAC_DW2_7996[] = {
+ {"AID", WF_LWTBL_AID_MASK, WF_LWTBL_AID_SHIFT, false},
+ {"GID_SU", WF_LWTBL_GID_SU_MASK, NO_SHIFT_DEFINE, false},
+ {"SPP_EN", WF_LWTBL_SPP_EN_MASK, NO_SHIFT_DEFINE, false},
+@@ -1032,6 +1033,26 @@ static const struct berse_wtbl_parse WTBL_LMAC_DW2[] = {
+ {NULL,}
+ };
+
++static const struct berse_wtbl_parse WTBL_LMAC_DW2_7992[] = {
++ {"AID", WF_LWTBL_AID_MASK, WF_LWTBL_AID_SHIFT, false},
++ {"GID_SU", WF_LWTBL_GID_SU_MASK, NO_SHIFT_DEFINE, false},
++ {"DUAL_PTEC_EN", WF_LWTBL_DUAL_PTEC_EN_MASK, NO_SHIFT_DEFINE, false},
++ {"DUAL_CTS_CAP", WF_LWTBL_DUAL_CTS_CAP_MASK, NO_SHIFT_DEFINE, false},
++ {"CIPHER_PGTK",WF_LWTBL_CIPHER_SUIT_PGTK_MASK, WF_LWTBL_CIPHER_SUIT_PGTK_SHIFT, true},
++ {"FROM_DS", WF_LWTBL_FD_MASK, NO_SHIFT_DEFINE, false},
++ {"TO_DS", WF_LWTBL_TD_MASK, NO_SHIFT_DEFINE, false},
++ {"SW", WF_LWTBL_SW_MASK, NO_SHIFT_DEFINE, false},
++ {"UL", WF_LWTBL_UL_MASK, NO_SHIFT_DEFINE, false},
++ {"TX_POWER_SAVE", WF_LWTBL_TX_PS_MASK, NO_SHIFT_DEFINE, true},
++ {"QOS", WF_LWTBL_QOS_MASK, NO_SHIFT_DEFINE, false},
++ {"HT", WF_LWTBL_HT_MASK, NO_SHIFT_DEFINE, false},
++ {"VHT", WF_LWTBL_VHT_MASK, NO_SHIFT_DEFINE, false},
++ {"HE", WF_LWTBL_HE_MASK, NO_SHIFT_DEFINE, false},
++ {"EHT", WF_LWTBL_EHT_MASK, NO_SHIFT_DEFINE, false},
++ {"MESH", WF_LWTBL_MESH_MASK, NO_SHIFT_DEFINE, true},
++ {NULL,}
++};
++
+ static void parse_fmac_lwtbl_dw2(struct seq_file *s, u8 *lwtbl)
+ {
+ u32 *addr = 0;
+@@ -1141,7 +1162,8 @@ static void parse_fmac_lwtbl_dw4(struct seq_file *s, u8 *lwtbl)
+ }
+ }
+
+-static const struct berse_wtbl_parse WTBL_LMAC_DW5[] = {
++static const struct berse_wtbl_parse *WTBL_LMAC_DW5;
++static const struct berse_wtbl_parse WTBL_LMAC_DW5_7996[] = {
+ {"AF", WF_LWTBL_AF_MASK, WF_LWTBL_AF_SHIFT, false},
+ {"AF_HE", WF_LWTBL_AF_HE_MASK, WF_LWTBL_AF_HE_SHIFT,false},
+ {"RTS", WF_LWTBL_RTS_MASK, NO_SHIFT_DEFINE, false},
+@@ -1163,6 +1185,27 @@ static const struct berse_wtbl_parse WTBL_LMAC_DW5[] = {
+ {NULL,}
+ };
+
++static const struct berse_wtbl_parse WTBL_LMAC_DW5_7992[] = {
++ {"AF", WF_LWTBL_AF_MASK_7992, WF_LWTBL_AF_SHIFT, false},
++ {"RTS", WF_LWTBL_RTS_MASK, NO_SHIFT_DEFINE, false},
++ {"SMPS", WF_LWTBL_SMPS_MASK, NO_SHIFT_DEFINE, false},
++ {"DYN_BW", WF_LWTBL_DYN_BW_MASK, NO_SHIFT_DEFINE, true},
++ {"MMSS", WF_LWTBL_MMSS_MASK, WF_LWTBL_MMSS_SHIFT,false},
++ {"USR", WF_LWTBL_USR_MASK, NO_SHIFT_DEFINE, false},
++ {"SR_RATE", WF_LWTBL_SR_R_MASK, WF_LWTBL_SR_R_SHIFT,false},
++ {"SR_ABORT", WF_LWTBL_SR_ABORT_MASK, NO_SHIFT_DEFINE, true},
++ {"TX_POWER_OFFSET", WF_LWTBL_TX_POWER_OFFSET_MASK, WF_LWTBL_TX_POWER_OFFSET_SHIFT, false},
++ {"LTF_EHT", WF_LWTBL_LTF_EHT_MASK, WF_LWTBL_LTF_EHT_SHIFT, false},
++ {"GI_EHT", WF_LWTBL_GI_EHT_MASK, WF_LWTBL_GI_EHT_SHIFT, false},
++ {"DOPPL", WF_LWTBL_DOPPL_MASK, NO_SHIFT_DEFINE, false},
++ {"TXOP_PS_CAP", WF_LWTBL_TXOP_PS_CAP_MASK, NO_SHIFT_DEFINE, false},
++ {"DONOT_UPDATE_I_PSM", WF_LWTBL_DU_I_PSM_MASK, NO_SHIFT_DEFINE, true},
++ {"I_PSM", WF_LWTBL_I_PSM_MASK, NO_SHIFT_DEFINE, false},
++ {"PSM", WF_LWTBL_PSM_MASK, NO_SHIFT_DEFINE, false},
++ {"SKIP_TX", WF_LWTBL_SKIP_TX_MASK, NO_SHIFT_DEFINE, true},
++ {NULL,}
++};
++
+ static void parse_fmac_lwtbl_dw5(struct seq_file *s, u8 *lwtbl)
+ {
+ u32 *addr = 0;
+@@ -1281,7 +1324,8 @@ static void parse_fmac_lwtbl_dw8(struct seq_file *s, u8 *lwtbl)
+ }
+ }
+
+-static const struct berse_wtbl_parse WTBL_LMAC_DW9[] = {
++static const struct berse_wtbl_parse *WTBL_LMAC_DW9;
++static const struct berse_wtbl_parse WTBL_LMAC_DW9_7996[] = {
+ {"RX_AVG_MPDU_SIZE", WF_LWTBL_RX_AVG_MPDU_SIZE_MASK, WF_LWTBL_RX_AVG_MPDU_SIZE_SHIFT, false},
+ {"PRITX_SW_MODE", WF_LWTBL_PRITX_SW_MODE_MASK, NO_SHIFT_DEFINE, false},
+ {"PRITX_ERSU", WF_LWTBL_PRITX_ERSU_MASK, NO_SHIFT_DEFINE, false},
+@@ -1295,6 +1339,20 @@ static const struct berse_wtbl_parse WTBL_LMAC_DW9[] = {
+ {NULL,}
+ };
+
++static const struct berse_wtbl_parse WTBL_LMAC_DW9_7992[] = {
++ {"RX_AVG_MPDU_SIZE", WF_LWTBL_RX_AVG_MPDU_SIZE_MASK, WF_LWTBL_RX_AVG_MPDU_SIZE_SHIFT, false},
++ {"PRITX_SW_MODE", WF_LWTBL_PRITX_SW_MODE_MASK_7992, NO_SHIFT_DEFINE, false},
++ {"PRITX_ERSU", WF_LWTBL_PRITX_ERSU_MASK_7992, NO_SHIFT_DEFINE, false},
++ {"PRITX_PLR", WF_LWTBL_PRITX_PLR_MASK_7992, NO_SHIFT_DEFINE, true},
++ {"PRITX_DCM", WF_LWTBL_PRITX_DCM_MASK, NO_SHIFT_DEFINE, false},
++ {"PRITX_ER106T", WF_LWTBL_PRITX_ER106T_MASK, NO_SHIFT_DEFINE, true},
++ /* {"FCAP(0:20 1:~40)", WTBL_FCAP_20_TO_160_MHZ, WTBL_FCAP_20_TO_160_MHZ_OFFSET}, */
++ {"MPDU_FAIL_CNT", WF_LWTBL_MPDU_FAIL_CNT_MASK, WF_LWTBL_MPDU_FAIL_CNT_SHIFT, false},
++ {"MPDU_OK_CNT", WF_LWTBL_MPDU_OK_CNT_MASK, WF_LWTBL_MPDU_OK_CNT_SHIFT, false},
++ {"RATE_IDX", WF_LWTBL_RATE_IDX_MASK, WF_LWTBL_RATE_IDX_SHIFT, true},
++ {NULL,}
++};
++
+ char *fcap_name[] = {"20MHz", "20/40MHz", "20/40/80MHz", "20/40/80/160/80+80MHz", "20/40/80/160/80+80/320MHz"};
+
+ static void parse_fmac_lwtbl_dw9(struct seq_file *s, u8 *lwtbl)
+@@ -2670,6 +2728,16 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ struct mt7996_dev *dev = phy->dev;
+
++ if (is_mt7996(&dev->mt76)) {
++ WTBL_LMAC_DW2 = WTBL_LMAC_DW2_7996;
++ WTBL_LMAC_DW5 = WTBL_LMAC_DW5_7996;
++ WTBL_LMAC_DW9 = WTBL_LMAC_DW9_7996;
++ } else {
++ WTBL_LMAC_DW2 = WTBL_LMAC_DW2_7992;
++ WTBL_LMAC_DW5 = WTBL_LMAC_DW5_7992;
++ WTBL_LMAC_DW9 = WTBL_LMAC_DW9_7992;
++ }
++
+ mt7996_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);
+
+ /* agg */
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
similarity index 65%
rename from recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
index 58605d3..d2800ea 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
@@ -1,51 +1,50 @@
-From 15b04fc966aa8f30492726132a6b81466b187581 Mon Sep 17 00:00:00 2001
+From cc82fae54b1efd7de07034bea7a883b9fb362799 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 6 Feb 2023 19:49:22 +0800
-Subject: [PATCH 2001/2008] wifi: mt76: revert page_poll for kernel 5.4
+Subject: [PATCH 64/98] wifi: mt76: revert page_poll for kernel 5.4
This reverts commit e8c10835cf062c577ddf426913788c39d30b4bd7.
Change-Id: I4e5764fc545087f691fb4c2f43e7a9cefd1e1657
---
- dma.c | 78 +++++++++++++++++++++++++++++----------------------
- mac80211.c | 57 -------------------------------------
+ dma.c | 75 +++++++++++++++++++++++++++------------------------
+ mac80211.c | 57 ---------------------------------------
+ mmio.c | 56 ++++++++++++++++++++++++--------------
mt76.h | 22 +--------------
- mt7915/main.c | 26 +++++++----------
- mt7915/mmio.c | 55 ++++++++++++++++++++++--------------
- mt7921/main.c | 31 +++-----------------
- usb.c | 43 ++++++++++++++--------------
- 7 files changed, 115 insertions(+), 197 deletions(-)
+ mt7915/main.c | 26 +++++++-----------
+ usb.c | 43 ++++++++++++++---------------
+ 6 files changed, 109 insertions(+), 170 deletions(-)
diff --git a/dma.c b/dma.c
-index 35db73b9..7153be47 100644
+index bb995e2..06b76ea 100644
--- a/dma.c
+++ b/dma.c
-@@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
+@@ -178,7 +178,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
local_bh_disable();
- while ((r = __mt76_get_rxwi(dev)) != NULL) {
- if (r->ptr)
-- mt76_put_page_pool_buf(r->ptr, false);
-+ skb_free_frag(r->ptr);
- kfree(r);
+ while ((t = __mt76_get_rxwi(dev)) != NULL) {
+ if (t->ptr)
+- mt76_put_page_pool_buf(t->ptr, false);
++ skb_free_frag(t->ptr);
+ kfree(t);
}
local_bh_enable();
-@@ -409,9 +409,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- if (!r)
+@@ -445,9 +445,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ if (!t)
return NULL;
-- dma_sync_single_for_cpu(dev->dma_dev, r->dma_addr,
+- dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
- SKB_WITH_OVERHEAD(q->buf_size),
- page_pool_get_dma_dir(q->page_pool));
-+ dma_unmap_single(dev->dma_dev, r->dma_addr,
++ dma_unmap_single(dev->dma_dev, t->dma_addr,
+ SKB_WITH_OVERHEAD(q->buf_size),
+ DMA_FROM_DEVICE);
- buf = r->ptr;
- r->dma_addr = 0;
-@@ -430,9 +430,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ buf = t->ptr;
+ t->dma_addr = 0;
+@@ -457,9 +457,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ if (drop)
+ *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
} else {
- buf = e->buf;
- e->buf = NULL;
- dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
- SKB_WITH_OVERHEAD(q->buf_size),
- page_pool_get_dma_dir(q->page_pool));
@@ -54,8 +53,8 @@
+ DMA_FROM_DEVICE);
}
- return buf;
-@@ -592,11 +592,11 @@ free_skb:
+ done:
+@@ -626,11 +626,11 @@ free_skb:
}
static int
@@ -70,15 +69,17 @@
if (!q->ndesc)
return 0;
-@@ -604,25 +604,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
- spin_lock_bh(&q->lock);
+@@ -639,28 +639,29 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
while (q->queued < q->ndesc - 1) {
+ struct mt76_queue_buf qbuf = {};
- enum dma_data_direction dir;
- struct mt76_queue_buf qbuf;
- dma_addr_t addr;
- int offset;
- void *buf;
+ void *buf = NULL;
+
+ if (mt76_queue_is_wed_rro_ind(q))
+ goto done;
- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
+ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
@@ -95,8 +96,9 @@
+ }
- qbuf.addr = addr + q->buf_offset;
-- qbuf.len = len - q->buf_offset;
+ qbuf.addr = addr + offset;
+ done:
+- qbuf.len = len - q->buf_offset;
+ qbuf.len = len - offset;
qbuf.skip_unmap = false;
if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
@@ -107,16 +109,25 @@
break;
}
frames++;
-@@ -666,7 +667,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -704,7 +705,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
/* 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, false);
+ mt76_dma_rx_fill(dev, q);
- q->flags = flags;
- ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -714,10 +715,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
+ if (!ret)
+@@ -733,7 +734,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ case MT76_WED_RRO_Q_IND:
+ q->flags &= ~MT_QFLAG_WED;
+ mt76_dma_queue_reset(dev, q);
+- mt76_dma_rx_fill(dev, q, false);
++ mt76_dma_rx_fill(dev, q);
+ mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
+ break;
+ default:
+@@ -789,10 +790,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (!q->entry)
return -ENOMEM;
@@ -127,7 +138,7 @@
ret = mt76_dma_wed_setup(dev, q, false);
if (ret)
return ret;
-@@ -731,6 +728,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -811,6 +808,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
static void
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
{
@@ -135,26 +146,21 @@
void *buf;
bool more;
-@@ -744,7 +742,10 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
- if (!buf)
+@@ -825,7 +823,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
break;
-- mt76_put_page_pool_buf(buf, false);
-+ if (q->flags & MT_QFLAG_RRO)
-+ continue;
-+
-+ skb_free_frag(buf);
+ if (!mt76_queue_is_wed_rro(q))
+- mt76_put_page_pool_buf(buf, false);
++ skb_free_frag(buf);
} while (1);
if (q->rx_head) {
-@@ -753,6 +754,18 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -834,6 +832,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
}
spin_unlock_bh(&q->lock);
+
-+ if (((q->flags & MT_QFLAG_WED) &&
-+ FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) ||
-+ (q->flags & MT_QFLAG_RRO))
++ if (mt76_queue_is_wed_rx(q))
+ return;
+
+ if (!q->rx_page.va)
@@ -166,16 +172,16 @@
}
static void
-@@ -773,7 +786,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -857,7 +865,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
mt76_dma_wed_setup(dev, q, true);
- if (q->flags != MT_WED_Q_TXFREE) {
+ if (!mt76_queue_is_wed_tx_free(q)) {
mt76_dma_sync_idx(dev, q);
- mt76_dma_rx_fill(dev, q, false);
+ mt76_dma_rx_fill(dev, q);
}
}
-@@ -791,7 +804,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -875,7 +883,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
} else {
@@ -184,7 +190,7 @@
}
if (more)
-@@ -864,7 +877,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -948,7 +956,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
goto free_frag;
skb_reserve(skb, q->buf_offset);
@@ -192,7 +198,7 @@
*(u32 *)skb->cb = info;
-@@ -880,10 +892,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -964,10 +971,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
continue;
free_frag:
@@ -205,7 +211,7 @@
return done;
}
-@@ -928,7 +940,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -1012,7 +1019,7 @@ mt76_dma_init(struct mt76_dev *dev,
mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -214,7 +220,7 @@
napi_enable(&dev->napi[i]);
}
-@@ -982,8 +994,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -1067,8 +1074,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q);
@@ -224,7 +230,7 @@
if (mtk_wed_device_active(&dev->mmio.wed))
diff --git a/mac80211.c b/mac80211.c
-index 5a203d31..f7578308 100644
+index 9c582cb..3715c73 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -4,7 +4,6 @@
@@ -235,7 +241,7 @@
#include "mt76.h"
static const struct ieee80211_channel mt76_channels_2ghz[] = {
-@@ -542,47 +541,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -546,47 +545,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
@@ -283,7 +289,7 @@
struct mt76_dev *
mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
-@@ -1728,21 +1686,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1786,21 +1744,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
}
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
@@ -305,11 +311,111 @@
enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
{
struct ieee80211_hw *hw = phy->hw;
+diff --git a/mmio.c b/mmio.c
+index c346249..5fb8392 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -89,8 +89,12 @@ EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
+ void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+ {
+ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++ u32 length;
+ int i;
+
++ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
++ sizeof(struct skb_shared_info));
++
+ for (i = 0; i < dev->rx_token_size; i++) {
+ struct mt76_txwi_cache *t;
+
+@@ -98,7 +102,9 @@ void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+ if (!t || !t->ptr)
+ continue;
+
+- mt76_put_page_pool_buf(t->ptr, false);
++ dma_unmap_single(dev->dma_dev, t->dma_addr,
++ wed->wlan.rx_size, DMA_FROM_DEVICE);
++ __free_pages(virt_to_page(t->ptr), get_order(length));
+ t->ptr = NULL;
+
+ mt76_put_rxwi(dev, t);
+@@ -112,33 +118,45 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ {
+ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+ struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
+- struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+- int i, len = SKB_WITH_OVERHEAD(q->buf_size);
+- struct mt76_txwi_cache *t = NULL;
++ u32 length;
++ int i;
++
++ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
++ sizeof(struct skb_shared_info));
+
+ for (i = 0; i < size; i++) {
+- enum dma_data_direction dir;
+- dma_addr_t addr;
+- u32 offset;
++ struct mt76_txwi_cache *t = mt76_get_rxwi(dev);
++ dma_addr_t phy_addr;
++ struct page *page;
+ int token;
+- void *buf;
++ void *ptr;
+
+- t = mt76_get_rxwi(dev);
+ if (!t)
+ goto unmap;
+
+- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
+- if (!buf)
+- goto unmap;
++ page = __dev_alloc_pages(GFP_KERNEL, get_order(length));
++ if (!page) {
++ mt76_put_rxwi(dev, t);
++ goto unmap;
++ }
+
+- addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
+- dir = page_pool_get_dma_dir(q->page_pool);
+- dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
++ phy_addr = dma_map_single(dev->dma_dev, ptr,
++ wed->wlan.rx_size,
++ DMA_TO_DEVICE);
+
+- desc->buf0 = cpu_to_le32(addr);
+- token = mt76_rx_token_consume(dev, buf, t, addr);
++ if (unlikely(dma_mapping_error(dev->dev, phy_addr))) {
++ skb_free_frag(ptr);
++ mt76_put_rxwi(dev, t);
++ goto unmap;
++ }
++
++ desc->buf0 = cpu_to_le32(phy_addr);
++ token = mt76_rx_token_consume(dev, ptr, t, phy_addr);
+ if (token < 0) {
+- mt76_put_page_pool_buf(buf, false);
++ dma_unmap_single(dev->dma_dev, phy_addr,
++ wed->wlan.rx_size, DMA_TO_DEVICE);
++ __free_pages(page, get_order(length));
++ mt76_put_rxwi(dev, t);
+ goto unmap;
+ }
+
+@@ -150,8 +168,6 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ return 0;
+
+ unmap:
+- if (t)
+- mt76_put_rxwi(dev, t);
+ mt76_mmio_wed_release_rx_buf(wed);
+
+ return -ENOMEM;
diff --git a/mt76.h b/mt76.h
-index 72c3eb8f..a0c20d36 100644
+index d59a1f5..3af97e5 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -224,7 +224,7 @@ struct mt76_queue {
+@@ -245,7 +245,7 @@ struct mt76_queue {
dma_addr_t desc_dma;
struct sk_buff *rx_head;
@@ -318,7 +424,7 @@
};
struct mt76_mcu_ops {
-@@ -1410,7 +1410,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+@@ -1566,7 +1566,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
@@ -326,10 +432,10 @@
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
struct mt76_sta_stats *stats, bool eht);
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
-@@ -1523,25 +1522,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
- struct mt76_rxwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
+@@ -1707,25 +1706,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+ struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
- struct mt76_rxwi_cache *r, dma_addr_t phys);
+ struct mt76_txwi_cache *r, dma_addr_t phys);
-int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q);
-static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
-{
@@ -353,21 +459,21 @@
static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
{
diff --git a/mt7915/main.c b/mt7915/main.c
-index 8ce7b1c5..fbff908f 100644
+index ba34c8e..4c80473 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
-@@ -1289,22 +1289,19 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
+@@ -1397,22 +1397,19 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data)
{
- if (sset != ETH_SS_STATS)
- return;
-
-- memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
+- memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
- data += sizeof(mt7915_gstrings_stats);
- page_pool_ethtool_stats_get_strings(data);
+ if (sset == ETH_SS_STATS)
-+ memcpy(data, *mt7915_gstrings_stats,
++ memcpy(data, mt7915_gstrings_stats,
+ sizeof(mt7915_gstrings_stats));
}
@@ -385,16 +491,16 @@
}
static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
-@@ -1332,7 +1329,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
+@@ -1440,7 +1437,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
+ .idx = mvif->mt76.idx,
};
- struct mib_stats *mib = &phy->mib;
/* See mt7915_ampdu_stat_read_phy, etc */
- int i, ei = 0, stats_size;
+ int i, ei = 0;
mutex_lock(&dev->mt76.mutex);
-@@ -1413,12 +1410,9 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
+@@ -1552,12 +1549,9 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
return;
ei += wi.worker_stat_count;
@@ -410,178 +516,8 @@
}
static void
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 46256842..8ff2c70c 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -596,9 +596,13 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
- static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
- {
- struct mt7915_dev *dev;
-+ u32 length;
- int i;
-
- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
-+ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
-+ sizeof(struct skb_shared_info));
-+
- for (i = 0; i < dev->mt76.rx_token_size; i++) {
- struct mt76_rxwi_cache *r;
-
-@@ -606,7 +610,9 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
- if (!r || !r->ptr)
- continue;
-
-- mt76_put_page_pool_buf(r->ptr, false);
-+ dma_unmap_single(dev->mt76.dma_dev, r->dma_addr,
-+ wed->wlan.rx_size, DMA_FROM_DEVICE);
-+ __free_pages(virt_to_page(r->ptr), get_order(length));
- r->ptr = NULL;
-
- mt76_put_rxwi(&dev->mt76, r);
-@@ -630,38 +636,47 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
- static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
- {
- struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
-- struct mt76_txwi_cache *t = NULL;
- struct mt7915_dev *dev;
-- struct mt76_queue *q;
-- int i, len;
-+ u32 length;
-+ int i;
-
- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
-- q = &dev->mt76.q_rx[MT_RXQ_MAIN];
-- len = SKB_WITH_OVERHEAD(q->buf_size);
-+ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
-+ sizeof(struct skb_shared_info));
-
- for (i = 0; i < size; i++) {
-- enum dma_data_direction dir;
-- dma_addr_t addr;
-- u32 offset;
-+ struct mt76_rxwi_cache *r = mt76_get_rxwi(&dev->mt76);
-+ dma_addr_t phy_addr;
-+ struct page *page;
- int token;
-- void *buf;
-+ void *ptr;
-
-- t = mt76_get_rxwi(&dev->mt76);
- if (!t)
- goto unmap;
-
-- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
-- if (!buf)
-+ page = __dev_alloc_pages(GFP_KERNEL, get_order(length));
-+ if (!page) {
-+ mt76_put_rxwi(&dev->mt76, r);
- goto unmap;
-+ }
-
-- addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
-- dir = page_pool_get_dma_dir(q->page_pool);
-- dma_sync_single_for_device(dev->mt76.dma_dev, addr, len, dir);
-+ ptr = page_address(page);
-+ phy_addr = dma_map_single(dev->mt76.dma_dev, ptr,
-+ wed->wlan.rx_size,
-+ DMA_TO_DEVICE);
-+ if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
-+ __free_pages(page, get_order(length));
-+ mt76_put_rxwi(&dev->mt76, r);
-+ goto unmap;
-+ }
-
-- desc->buf0 = cpu_to_le32(addr);
-- token = mt76_rx_token_consume(&dev->mt76, buf, t, addr);
-+ desc->buf0 = cpu_to_le32(phy_addr);
-+ token = mt76_rx_token_consume(&dev->mt76, ptr, r, phy_addr);
- if (token < 0) {
-- mt76_put_page_pool_buf(buf, false);
-+ dma_unmap_single(dev->mt76.dma_dev, phy_addr,
-+ wed->wlan.rx_size, DMA_TO_DEVICE);
-+ __free_pages(page, get_order(length));
-+ mt76_put_rxwi(&dev->mt76, r);
- goto unmap;
- }
-
-@@ -673,8 +688,6 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
- return 0;
-
- unmap:
-- if (t)
-- mt76_put_rxwi(&dev->mt76, t);
- mt7915_mmio_wed_release_rx_buf(wed);
- return -ENOMEM;
- }
-diff --git a/mt7921/main.c b/mt7921/main.c
-index 3b6adb29..47eb38e4 100644
---- a/mt7921/main.c
-+++ b/mt7921/main.c
-@@ -1083,34 +1083,17 @@ static void
- mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u32 sset, u8 *data)
- {
-- struct mt7921_dev *dev = mt7921_hw_dev(hw);
--
- if (sset != ETH_SS_STATS)
- return;
-
- memcpy(data, *mt7921_gstrings_stats, sizeof(mt7921_gstrings_stats));
--
-- if (mt76_is_sdio(&dev->mt76))
-- return;
--
-- data += sizeof(mt7921_gstrings_stats);
-- page_pool_ethtool_stats_get_strings(data);
- }
-
- static int
- mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int sset)
- {
-- struct mt7921_dev *dev = mt7921_hw_dev(hw);
--
-- if (sset != ETH_SS_STATS)
-- return 0;
--
-- if (mt76_is_sdio(&dev->mt76))
-- return ARRAY_SIZE(mt7921_gstrings_stats);
--
-- return ARRAY_SIZE(mt7921_gstrings_stats) +
-- page_pool_ethtool_stats_get_count();
-+ return sset == ETH_SS_STATS ? ARRAY_SIZE(mt7921_gstrings_stats) : 0;
- }
-
- static void
-@@ -1130,7 +1113,6 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ethtool_stats *stats, u64 *data)
- {
- struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
-- int stats_size = ARRAY_SIZE(mt7921_gstrings_stats);
- struct mt7921_phy *phy = mt7921_hw_phy(hw);
- struct mt7921_dev *dev = phy->dev;
- struct mib_stats *mib = &phy->mib;
-@@ -1186,14 +1168,9 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- return;
-
- ei += wi.worker_stat_count;
--
-- if (!mt76_is_sdio(&dev->mt76)) {
-- mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);
-- stats_size += page_pool_ethtool_stats_get_count();
-- }
--
-- if (ei != stats_size)
-- dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, stats_size);
-+ if (ei != ARRAY_SIZE(mt7921_gstrings_stats))
-+ dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %zu",
-+ ei, ARRAY_SIZE(mt7921_gstrings_stats));
- }
-
- static u64
diff --git a/usb.c b/usb.c
-index 5e5c7bf5..3e281715 100644
+index 5e5c7bf..3e28171 100644
--- a/usb.c
+++ b/usb.c
@@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
@@ -715,5 +651,5 @@
static void mt76u_free_rx(struct mt76_dev *dev)
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch
deleted file mode 100644
index 050c6f2..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch
+++ /dev/null
@@ -1,443 +0,0 @@
-From 06c6ad7b99c07aedc5403506c91cbb8e11cf95df Mon Sep 17 00:00:00 2001
-From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Mon, 6 Feb 2023 13:37:23 +0800
-Subject: [PATCH 2000/2008] wifi: mt76: rework wed rx flow
-
-Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
-Change-Id: Icd787345c811cb5ad30d9c7c1c5f9e5298bd3be6
----
- dma.c | 89 +++++++++++++++++++++++++------------------------
- mac80211.c | 2 +-
- mt76.h | 23 ++++++++-----
- mt7915/dma.c | 2 --
- mt7915/mmio.c | 27 +++++++++++----
- mt7915/mt7915.h | 1 +
- tx.c | 16 ++++-----
- 7 files changed, 90 insertions(+), 70 deletions(-)
-
-diff --git a/dma.c b/dma.c
-index e1e9062b..35db73b9 100644
---- a/dma.c
-+++ b/dma.c
-@@ -59,17 +59,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
- return t;
- }
-
--static struct mt76_txwi_cache *
-+static struct mt76_rxwi_cache *
- mt76_alloc_rxwi(struct mt76_dev *dev)
- {
-- struct mt76_txwi_cache *t;
-+ struct mt76_rxwi_cache *r;
-
-- t = kzalloc(L1_CACHE_ALIGN(sizeof(*t)), GFP_ATOMIC);
-- if (!t)
-+ r = kzalloc(L1_CACHE_ALIGN(sizeof(*r)), GFP_ATOMIC);
-+ if (!r)
- return NULL;
-
-- t->ptr = NULL;
-- return t;
-+ r->ptr = NULL;
-+ return r;
- }
-
- static struct mt76_txwi_cache *
-@@ -88,20 +88,20 @@ __mt76_get_txwi(struct mt76_dev *dev)
- return t;
- }
-
--static struct mt76_txwi_cache *
-+static struct mt76_rxwi_cache *
- __mt76_get_rxwi(struct mt76_dev *dev)
- {
-- struct mt76_txwi_cache *t = NULL;
-+ struct mt76_rxwi_cache *r = NULL;
-
-- spin_lock(&dev->wed_lock);
-+ spin_lock(&dev->lock);
- if (!list_empty(&dev->rxwi_cache)) {
-- t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
-+ r = list_first_entry(&dev->rxwi_cache, struct mt76_rxwi_cache,
- list);
-- list_del(&t->list);
-+ list_del(&r->list);
- }
-- spin_unlock(&dev->wed_lock);
-+ spin_unlock(&dev->lock);
-
-- return t;
-+ return r;
- }
-
- static struct mt76_txwi_cache *
-@@ -115,13 +115,13 @@ mt76_get_txwi(struct mt76_dev *dev)
- return mt76_alloc_txwi(dev);
- }
-
--struct mt76_txwi_cache *
-+struct mt76_rxwi_cache *
- mt76_get_rxwi(struct mt76_dev *dev)
- {
-- struct mt76_txwi_cache *t = __mt76_get_rxwi(dev);
-+ struct mt76_rxwi_cache *r = __mt76_get_rxwi(dev);
-
-- if (t)
-- return t;
-+ if (r)
-+ return r;
-
- return mt76_alloc_rxwi(dev);
- }
-@@ -140,14 +140,14 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- EXPORT_SYMBOL_GPL(mt76_put_txwi);
-
- void
--mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+mt76_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r)
- {
-- if (!t)
-+ if (!r)
- return;
-
-- spin_lock(&dev->wed_lock);
-- list_add(&t->list, &dev->rxwi_cache);
-- spin_unlock(&dev->wed_lock);
-+ spin_lock(&dev->lock);
-+ list_add(&r->list, &dev->rxwi_cache);
-+ spin_unlock(&dev->lock);
- }
- EXPORT_SYMBOL_GPL(mt76_put_rxwi);
-
-@@ -168,13 +168,13 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
- void
- mt76_free_pending_rxwi(struct mt76_dev *dev)
- {
-- struct mt76_txwi_cache *t;
-+ struct mt76_rxwi_cache *r;
-
- local_bh_disable();
-- while ((t = __mt76_get_rxwi(dev)) != NULL) {
-- if (t->ptr)
-- mt76_put_page_pool_buf(t->ptr, false);
-- kfree(t);
-+ while ((r = __mt76_get_rxwi(dev)) != NULL) {
-+ if (r->ptr)
-+ mt76_put_page_pool_buf(r->ptr, false);
-+ kfree(r);
- }
- local_bh_enable();
- }
-@@ -212,7 +212,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
- {
- struct mt76_desc *desc = &q->desc[q->head];
- struct mt76_queue_entry *entry = &q->entry[q->head];
-- struct mt76_txwi_cache *txwi = NULL;
-+ struct mt76_rxwi_cache *rxwi = NULL;
- u32 buf1 = 0, ctrl;
- int idx = q->head;
- int rx_token;
-@@ -220,13 +220,13 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
- ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
-
- if (mt76_queue_is_wed_rx(q)) {
-- txwi = mt76_get_rxwi(dev);
-- if (!txwi)
-+ rxwi = mt76_get_rxwi(dev);
-+ if (!rxwi)
- return -ENOMEM;
-
-- rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr);
-+ rx_token = mt76_rx_token_consume(dev, data, rxwi, buf->addr);
- if (rx_token < 0) {
-- mt76_put_rxwi(dev, txwi);
-+ mt76_put_rxwi(dev, rxwi);
- return -ENOMEM;
- }
-
-@@ -241,7 +241,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
-
- entry->dma_addr[0] = buf->addr;
- entry->dma_len[0] = buf->len;
-- entry->txwi = txwi;
-+ entry->rxwi = rxwi;
- entry->buf = data;
- entry->wcid = 0xffff;
- entry->skip_buf1 = true;
-@@ -404,20 +404,20 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- if (mt76_queue_is_wed_rx(q)) {
- u32 buf1 = le32_to_cpu(desc->buf1);
- u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
-- struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
-+ struct mt76_rxwi_cache *r = mt76_rx_token_release(dev, token);
-
-- if (!t)
-+ if (!r)
- return NULL;
-
-- dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
-+ dma_sync_single_for_cpu(dev->dma_dev, r->dma_addr,
- SKB_WITH_OVERHEAD(q->buf_size),
- page_pool_get_dma_dir(q->page_pool));
-
-- buf = t->ptr;
-- t->dma_addr = 0;
-- t->ptr = NULL;
-+ buf = r->ptr;
-+ r->dma_addr = 0;
-+ r->ptr = NULL;
-
-- mt76_put_rxwi(dev, t);
-+ mt76_put_rxwi(dev, r);
-
- if (drop) {
- u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
-@@ -977,16 +977,19 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
- mt76_for_each_q_rx(dev, i) {
- struct mt76_queue *q = &dev->q_rx[i];
-
-+ if (mt76_queue_is_wed_rx(q))
-+ continue;
-+
- netif_napi_del(&dev->napi[i]);
- mt76_dma_rx_cleanup(dev, q);
-
- page_pool_destroy(q->page_pool);
- }
-
-- mt76_free_pending_txwi(dev);
-- mt76_free_pending_rxwi(dev);
--
- if (mtk_wed_device_active(&dev->mmio.wed))
- mtk_wed_device_detach(&dev->mmio.wed);
-+
-+ mt76_free_pending_txwi(dev);
-+ mt76_free_pending_rxwi(dev);
- }
- EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
-diff --git a/mac80211.c b/mac80211.c
-index 6430e6ee..5a203d31 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -613,7 +613,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
- spin_lock_init(&dev->lock);
- spin_lock_init(&dev->cc_lock);
- spin_lock_init(&dev->status_lock);
-- spin_lock_init(&dev->wed_lock);
- mutex_init(&dev->mutex);
- init_waitqueue_head(&dev->tx_wait);
-
-@@ -644,6 +643,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
- INIT_LIST_HEAD(&dev->txwi_cache);
- INIT_LIST_HEAD(&dev->rxwi_cache);
- dev->token_size = dev->drv->token_size;
-+ dev->rx_token_size = dev->drv->rx_token_size;
-
- for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
- skb_queue_head_init(&dev->rx_skb[i]);
-diff --git a/mt76.h b/mt76.h
-index 8abb6f41..72c3eb8f 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -180,6 +180,7 @@ struct mt76_queue_entry {
- };
- union {
- struct mt76_txwi_cache *txwi;
-+ struct mt76_rxwi_cache *rxwi;
- struct urb *urb;
- int buf_sz;
- };
-@@ -371,10 +372,14 @@ struct mt76_txwi_cache {
- struct list_head list;
- dma_addr_t dma_addr;
-
-- union {
-- struct sk_buff *skb;
-- void *ptr;
-- };
-+ struct sk_buff *skb;
-+};
-+
-+struct mt76_rxwi_cache {
-+ struct list_head list;
-+ dma_addr_t dma_addr;
-+
-+ void *ptr;
- };
-
- struct mt76_rx_tid {
-@@ -460,6 +465,7 @@ struct mt76_driver_ops {
- u16 txwi_size;
- u16 token_size;
- u8 mcs_rates;
-+ u16 rx_token_size;
-
- void (*update_survey)(struct mt76_phy *phy);
-
-@@ -810,7 +816,6 @@ struct mt76_dev {
-
- struct ieee80211_hw *hw;
-
-- spinlock_t wed_lock;
- spinlock_t lock;
- spinlock_t cc_lock;
-
-@@ -1360,8 +1365,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_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r);
-+struct mt76_rxwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
- void mt76_free_pending_rxwi(struct mt76_dev *dev);
- void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
- struct napi_struct *napi);
-@@ -1515,9 +1520,9 @@ 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);
--struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
-+struct mt76_rxwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
- int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
-- struct mt76_txwi_cache *r, dma_addr_t phys);
-+ struct mt76_rxwi_cache *r, dma_addr_t phys);
- int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q);
- static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
- {
-diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 86a93ded..848e9843 100644
---- a/mt7915/dma.c
-+++ b/mt7915/dma.c
-@@ -493,7 +493,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
- mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
- dev->mt76.q_rx[MT_RXQ_MAIN].flags =
- MT_WED_Q_RX(MT7915_RXQ_BAND0);
-- dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
- }
-
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
-@@ -530,7 +529,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
- mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
- dev->mt76.q_rx[MT_RXQ_BAND1].flags =
- MT_WED_Q_RX(MT7915_RXQ_BAND1);
-- dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
- }
-
- /* rx data queue for band1 */
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 984b5f60..46256842 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -600,16 +600,28 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
-
- dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
- for (i = 0; i < dev->mt76.rx_token_size; i++) {
-- struct mt76_txwi_cache *t;
-+ struct mt76_rxwi_cache *r;
-
-- t = mt76_rx_token_release(&dev->mt76, i);
-- if (!t || !t->ptr)
-+ r = mt76_rx_token_release(&dev->mt76, i);
-+ if (!r || !r->ptr)
- continue;
-
-- mt76_put_page_pool_buf(t->ptr, false);
-- t->ptr = NULL;
-+ mt76_put_page_pool_buf(r->ptr, false);
-+ r->ptr = NULL;
-
-- mt76_put_rxwi(&dev->mt76, t);
-+ mt76_put_rxwi(&dev->mt76, r);
-+ }
-+
-+ mt76_for_each_q_rx(dev, i) {
-+ struct mt76_queue *q = &dev->q_rx[i];
-+
-+ if (!mt76_queue_is_wed_rx(q))
-+ continue;
-+
-+ netif_napi_del(&dev->napi[i]);
-+ mt76_dma_rx_cleanup(dev, q);
-+
-+ page_pool_destroy(q->page_pool);
- }
-
- mt76_free_pending_rxwi(&dev->mt76);
-@@ -812,7 +824,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
- wed->wlan.reset = mt7915_mmio_wed_reset;
- wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete;
-
-- dev->mt76.rx_token_size = wed->wlan.rx_npkt;
-+ dev->mt76.rx_token_size += wed->wlan.rx_npkt;
-
- if (mtk_wed_device_attach(wed))
- return 0;
-@@ -1018,6 +1030,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
- SURVEY_INFO_TIME_RX |
- SURVEY_INFO_TIME_BSS_RX,
- .token_size = MT7915_TOKEN_SIZE,
-+ .rx_token_size = MT7915_RX_TOKEN_SIZE;
- .tx_prepare_skb = mt7915_tx_prepare_skb,
- .tx_complete_skb = mt76_connac_tx_complete_skb,
- .rx_skb = mt7915_queue_rx_skb,
-diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 103cd0d7..8ee62f63 100644
---- a/mt7915/mt7915.h
-+++ b/mt7915/mt7915.h
-@@ -62,6 +62,7 @@
- #define MT7915_EEPROM_BLOCK_SIZE 16
- #define MT7915_HW_TOKEN_SIZE 4096
- #define MT7915_TOKEN_SIZE 8192
-+#define MT7915_RX_TOKEN_SIZE 4096
-
- #define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
- #define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
-diff --git a/tx.c b/tx.c
-index 72b3ec71..6cb71f34 100644
---- a/tx.c
-+++ b/tx.c
-@@ -761,16 +761,16 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
- EXPORT_SYMBOL_GPL(mt76_token_consume);
-
- int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
-- struct mt76_txwi_cache *t, dma_addr_t phys)
-+ struct mt76_rxwi_cache *r, dma_addr_t phys)
- {
- int token;
-
- spin_lock_bh(&dev->rx_token_lock);
-- token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size,
-+ token = idr_alloc(&dev->rx_token, r, 0, dev->rx_token_size,
- GFP_ATOMIC);
- if (token >= 0) {
-- t->ptr = ptr;
-- t->dma_addr = phys;
-+ r->ptr = ptr;
-+ r->dma_addr = phys;
- }
- spin_unlock_bh(&dev->rx_token_lock);
-
-@@ -807,15 +807,15 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
- }
- EXPORT_SYMBOL_GPL(mt76_token_release);
-
--struct mt76_txwi_cache *
-+struct mt76_rxwi_cache *
- mt76_rx_token_release(struct mt76_dev *dev, int token)
- {
-- struct mt76_txwi_cache *t;
-+ struct mt76_rxwi_cache *r;
-
- spin_lock_bh(&dev->rx_token_lock);
-- t = idr_remove(&dev->rx_token, token);
-+ r = idr_remove(&dev->rx_token, token);
- spin_unlock_bh(&dev->rx_token_lock);
-
-- return t;
-+ return r;
- }
- EXPORT_SYMBOL_GPL(mt76_rx_token_release);
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-rework-wed-rx-flow.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-rework-wed-rx-flow.patch
new file mode 100644
index 0000000..a0854af
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-rework-wed-rx-flow.patch
@@ -0,0 +1,539 @@
+From 78b8b86fce85c8ff6fad935bd9bd8b2df0e151ab Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 13:37:23 +0800
+Subject: [PATCH 65/98] wifi: mt76: rework wed rx flow
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Change-Id: Icd787345c811cb5ad30d9c7c1c5f9e5298bd3be6
+---
+ dma.c | 125 +++++++++++++++++++++++++++++++-----------------
+ mac80211.c | 2 +-
+ mmio.c | 58 ++++++++++++++--------
+ mt76.h | 23 +++++----
+ mt7915/mmio.c | 3 +-
+ mt7915/mt7915.h | 1 +
+ tx.c | 16 +++----
+ 7 files changed, 143 insertions(+), 85 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 06b76ea..f48ec57 100644
+--- a/dma.c
++++ b/dma.c
+@@ -64,17 +64,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
+ return t;
+ }
+
+-static struct mt76_txwi_cache *
++static struct mt76_rxwi_cache *
+ mt76_alloc_rxwi(struct mt76_dev *dev)
+ {
+- struct mt76_txwi_cache *t;
++ struct mt76_rxwi_cache *r;
+
+- t = kzalloc(L1_CACHE_ALIGN(sizeof(*t)), GFP_ATOMIC);
+- if (!t)
++ r = kzalloc(L1_CACHE_ALIGN(sizeof(*r)), GFP_ATOMIC);
++ if (!r)
+ return NULL;
+
+- t->ptr = NULL;
+- return t;
++ r->ptr = NULL;
++ return r;
+ }
+
+ static struct mt76_txwi_cache *
+@@ -93,20 +93,20 @@ __mt76_get_txwi(struct mt76_dev *dev)
+ return t;
+ }
+
+-static struct mt76_txwi_cache *
++static struct mt76_rxwi_cache *
+ __mt76_get_rxwi(struct mt76_dev *dev)
+ {
+- struct mt76_txwi_cache *t = NULL;
++ struct mt76_rxwi_cache *r = NULL;
+
+- spin_lock(&dev->wed_lock);
++ spin_lock(&dev->lock);
+ if (!list_empty(&dev->rxwi_cache)) {
+- t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
++ r = list_first_entry(&dev->rxwi_cache, struct mt76_rxwi_cache,
+ list);
+- list_del(&t->list);
++ list_del(&r->list);
+ }
+- spin_unlock(&dev->wed_lock);
++ spin_unlock(&dev->lock);
+
+- return t;
++ return r;
+ }
+
+ static struct mt76_txwi_cache *
+@@ -120,13 +120,13 @@ mt76_get_txwi(struct mt76_dev *dev)
+ return mt76_alloc_txwi(dev);
+ }
+
+-struct mt76_txwi_cache *
++struct mt76_rxwi_cache *
+ mt76_get_rxwi(struct mt76_dev *dev)
+ {
+- struct mt76_txwi_cache *t = __mt76_get_rxwi(dev);
++ struct mt76_rxwi_cache *r = __mt76_get_rxwi(dev);
+
+- if (t)
+- return t;
++ if (r)
++ return r;
+
+ return mt76_alloc_rxwi(dev);
+ }
+@@ -145,14 +145,14 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
+ EXPORT_SYMBOL_GPL(mt76_put_txwi);
+
+ void
+-mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
++mt76_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r)
+ {
+- if (!t)
++ if (!r)
+ return;
+
+- spin_lock(&dev->wed_lock);
+- list_add(&t->list, &dev->rxwi_cache);
+- spin_unlock(&dev->wed_lock);
++ spin_lock(&dev->lock);
++ list_add(&r->list, &dev->rxwi_cache);
++ spin_unlock(&dev->lock);
+ }
+ EXPORT_SYMBOL_GPL(mt76_put_rxwi);
+
+@@ -173,13 +173,13 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+ void
+ mt76_free_pending_rxwi(struct mt76_dev *dev)
+ {
+- struct mt76_txwi_cache *t;
++ struct mt76_rxwi_cache *r;
+
+ local_bh_disable();
+- while ((t = __mt76_get_rxwi(dev)) != NULL) {
+- if (t->ptr)
+- skb_free_frag(t->ptr);
+- kfree(t);
++ while ((r = __mt76_get_rxwi(dev)) != NULL) {
++ if (r->ptr)
++ skb_free_frag(r->ptr);
++ kfree(r);
+ }
+ local_bh_enable();
+ }
+@@ -227,10 +227,10 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
+
+ static int
+ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+- struct mt76_queue_buf *buf, void *data)
++ struct mt76_queue_buf *buf, void *data,
++ struct mt76_rxwi_cache *rxwi)
+ {
+ struct mt76_queue_entry *entry = &q->entry[q->head];
+- struct mt76_txwi_cache *txwi = NULL;
+ struct mt76_desc *desc;
+ u32 buf1 = 0, ctrl;
+ int idx = q->head;
+@@ -248,13 +248,15 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+
+ if (mt76_queue_is_wed_rx(q)) {
+- txwi = mt76_get_rxwi(dev);
+- if (!txwi)
+- return -ENOMEM;
++ if (!rxwi) {
++ rxwi = mt76_get_rxwi(dev);
++ if (!rxwi)
++ return -ENOMEM;
++ }
+
+- rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr);
++ rx_token = mt76_rx_token_consume(dev, data, rxwi, buf->addr);
+ if (rx_token < 0) {
+- mt76_put_rxwi(dev, txwi);
++ mt76_put_rxwi(dev, rxwi);
+ return -ENOMEM;
+ }
+
+@@ -270,7 +272,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ done:
+ entry->dma_addr[0] = buf->addr;
+ entry->dma_len[0] = buf->len;
+- entry->txwi = txwi;
++ entry->rxwi = rxwi;
+ entry->buf = data;
+ entry->wcid = 0xffff;
+ entry->skip_buf1 = true;
+@@ -412,7 +414,7 @@ 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, bool *drop)
++ int *len, u32 *info, bool *more, bool *drop, bool flush)
+ {
+ struct mt76_queue_entry *e = &q->entry[idx];
+ struct mt76_desc *desc = &q->desc[idx];
+@@ -440,20 +442,53 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ if (mt76_queue_is_wed_rx(q)) {
+ u32 buf1 = le32_to_cpu(desc->buf1);
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
+- struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
++ struct mt76_rxwi_cache *r = mt76_rx_token_release(dev, token);
+
+- if (!t)
++ if (!r)
+ return NULL;
+
+- dma_unmap_single(dev->dma_dev, t->dma_addr,
++ dma_unmap_single(dev->dma_dev, r->dma_addr,
+ SKB_WITH_OVERHEAD(q->buf_size),
+ DMA_FROM_DEVICE);
+
+- buf = t->ptr;
+- t->dma_addr = 0;
+- t->ptr = NULL;
++ if (flush) {
++ buf = r->ptr;
++ r->dma_addr = 0;
++ r->ptr = NULL;
++
++ mt76_put_rxwi(dev, r);
++ } else {
++ struct mt76_queue_buf qbuf;
++
++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ if (!buf)
++ return NULL;
++
++ memcpy(buf, r->ptr, SKB_WITH_OVERHEAD(q->buf_size));
++
++ r->dma_addr = dma_map_single(dev->dma_dev, r->ptr,
++ SKB_WITH_OVERHEAD(q->buf_size),
++ DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(dev->dma_dev, r->dma_addr))) {
++ skb_free_frag(r->ptr);
++ mt76_put_rxwi(dev, r);
++ return NULL;
++ }
++
++ qbuf.addr = r->dma_addr;
++ qbuf.len = SKB_WITH_OVERHEAD(q->buf_size);
++ qbuf.skip_unmap = false;
++
++ if (mt76_dma_add_rx_buf(dev, q, &qbuf, r->ptr, r) < 0) {
++ dma_unmap_single(dev->dma_dev, r->dma_addr,
++ SKB_WITH_OVERHEAD(q->buf_size),
++ DMA_FROM_DEVICE);
++ skb_free_frag(r->ptr);
++ mt76_put_rxwi(dev, r);
++ return NULL;
++ }
++ }
+
+- mt76_put_rxwi(dev, t);
+ if (drop)
+ *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
+ } else {
+@@ -490,7 +525,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, drop);
++ return mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);
+ }
+
+ static int
+@@ -658,7 +693,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ done:
+ qbuf.len = len - offset;
+ qbuf.skip_unmap = false;
+- if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
++ if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf, NULL) < 0) {
+ dma_unmap_single(dev->dma_dev, addr, len,
+ DMA_FROM_DEVICE);
+ skb_free_frag(buf);
+diff --git a/mac80211.c b/mac80211.c
+index 3715c73..4552bc2 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -575,7 +575,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ spin_lock_init(&dev->lock);
+ spin_lock_init(&dev->cc_lock);
+ spin_lock_init(&dev->status_lock);
+- spin_lock_init(&dev->wed_lock);
+ mutex_init(&dev->mutex);
+ init_waitqueue_head(&dev->tx_wait);
+
+@@ -608,6 +607,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ INIT_LIST_HEAD(&dev->txwi_cache);
+ INIT_LIST_HEAD(&dev->rxwi_cache);
+ dev->token_size = dev->drv->token_size;
++ dev->rx_token_size = dev->drv->rx_token_size;
+
+ for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
+ skb_queue_head_init(&dev->rx_skb[i]);
+diff --git a/mmio.c b/mmio.c
+index 5fb8392..f7495f6 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -89,28 +89,45 @@ EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
+ void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+ {
+ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+- u32 length;
++ struct page *page;
+ int i;
+
+- length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
+- sizeof(struct skb_shared_info));
+-
+ for (i = 0; i < dev->rx_token_size; i++) {
+- struct mt76_txwi_cache *t;
++ struct mt76_rxwi_cache *r;
+
+- t = mt76_rx_token_release(dev, i);
+- if (!t || !t->ptr)
++ r = mt76_rx_token_release(dev, i);
++ if (!r || !r->ptr)
+ continue;
+
+- dma_unmap_single(dev->dma_dev, t->dma_addr,
++ dma_unmap_single(dev->dma_dev, r->dma_addr,
+ wed->wlan.rx_size, DMA_FROM_DEVICE);
+- __free_pages(virt_to_page(t->ptr), get_order(length));
+- t->ptr = NULL;
++ skb_free_frag(r->ptr);
++ r->ptr = NULL;
+
+- mt76_put_rxwi(dev, t);
++ mt76_put_rxwi(dev, r);
+ }
+
+ mt76_free_pending_rxwi(dev);
++
++ mt76_for_each_q_rx(dev, i) {
++ struct mt76_queue *q = &dev->q_rx[i];
++
++ if (mt76_queue_is_wed_rx(q)) {
++ if (!q->rx_page.va)
++ continue;
++
++ page = virt_to_page(q->rx_page.va);
++ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
++ memset(&q->rx_page, 0, sizeof(q->rx_page));
++ }
++ }
++
++ if (!wed->rx_buf_ring.rx_page.va)
++ return;
++
++ page = virt_to_page(wed->rx_buf_ring.rx_page.va);
++ __page_frag_cache_drain(page, wed->rx_buf_ring.rx_page.pagecnt_bias);
++ memset(&wed->rx_buf_ring.rx_page, 0, sizeof(wed->rx_buf_ring.rx_page));
+ }
+ EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);
+
+@@ -125,18 +142,17 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ sizeof(struct skb_shared_info));
+
+ for (i = 0; i < size; i++) {
+- struct mt76_txwi_cache *t = mt76_get_rxwi(dev);
++ struct mt76_rxwi_cache *r = mt76_get_rxwi(dev);
+ dma_addr_t phy_addr;
+- struct page *page;
+ int token;
+ void *ptr;
+
+- if (!t)
++ if (!r)
+ goto unmap;
+
+- page = __dev_alloc_pages(GFP_KERNEL, get_order(length));
+- if (!page) {
+- mt76_put_rxwi(dev, t);
++ ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length, GFP_ATOMIC);
++ if (!ptr) {
++ mt76_put_rxwi(dev, r);
+ goto unmap;
+ }
+
+@@ -146,17 +162,17 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+
+ if (unlikely(dma_mapping_error(dev->dev, phy_addr))) {
+ skb_free_frag(ptr);
+- mt76_put_rxwi(dev, t);
++ mt76_put_rxwi(dev, r);
+ goto unmap;
+ }
+
+ desc->buf0 = cpu_to_le32(phy_addr);
+- token = mt76_rx_token_consume(dev, ptr, t, phy_addr);
++ token = mt76_rx_token_consume(dev, ptr, r, phy_addr);
+ if (token < 0) {
+ dma_unmap_single(dev->dma_dev, phy_addr,
+ wed->wlan.rx_size, DMA_TO_DEVICE);
+- __free_pages(page, get_order(length));
+- mt76_put_rxwi(dev, t);
++ skb_free_frag(ptr);
++ mt76_put_rxwi(dev, r);
+ goto unmap;
+ }
+
+diff --git a/mt76.h b/mt76.h
+index 3af97e5..b960f3d 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -200,6 +200,7 @@ struct mt76_queue_entry {
+ };
+ union {
+ struct mt76_txwi_cache *txwi;
++ struct mt76_rxwi_cache *rxwi;
+ struct urb *urb;
+ int buf_sz;
+ };
+@@ -410,10 +411,14 @@ struct mt76_txwi_cache {
+ struct list_head list;
+ dma_addr_t dma_addr;
+
+- union {
+- struct sk_buff *skb;
+- void *ptr;
+- };
++ struct sk_buff *skb;
++};
++
++struct mt76_rxwi_cache {
++ struct list_head list;
++ dma_addr_t dma_addr;
++
++ void *ptr;
+ };
+
+ struct mt76_rx_tid {
+@@ -499,6 +504,7 @@ struct mt76_driver_ops {
+ u16 txwi_size;
+ u16 token_size;
+ u8 mcs_rates;
++ u16 rx_token_size;
+
+ void (*update_survey)(struct mt76_phy *phy);
+
+@@ -858,7 +864,6 @@ struct mt76_dev {
+
+ struct ieee80211_hw *hw;
+
+- spinlock_t wed_lock;
+ spinlock_t lock;
+ spinlock_t cc_lock;
+
+@@ -1521,8 +1526,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_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r);
++struct mt76_rxwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
+ void mt76_free_pending_rxwi(struct mt76_dev *dev);
+ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
+ struct napi_struct *napi);
+@@ -1703,9 +1708,9 @@ 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);
+-struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
++struct mt76_rxwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
+ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
+- struct mt76_txwi_cache *r, dma_addr_t phys);
++ struct mt76_rxwi_cache *r, dma_addr_t phys);
+
+ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
+ {
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index 85cb3fe..690cac5 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -687,7 +687,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
+ wed->wlan.reset = mt7915_mmio_wed_reset;
+ wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete;
+
+- dev->mt76.rx_token_size = wed->wlan.rx_npkt;
++ dev->mt76.rx_token_size += wed->wlan.rx_npkt;
+
+ if (mtk_wed_device_attach(wed))
+ return 0;
+@@ -893,6 +893,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
+ SURVEY_INFO_TIME_RX |
+ SURVEY_INFO_TIME_BSS_RX,
+ .token_size = MT7915_TOKEN_SIZE,
++ .rx_token_size = MT7915_RX_TOKEN_SIZE;
+ .tx_prepare_skb = mt7915_tx_prepare_skb,
+ .tx_complete_skb = mt76_connac_tx_complete_skb,
+ .rx_skb = mt7915_queue_rx_skb,
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index d317c52..91eb5ad 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -62,6 +62,7 @@
+ #define MT7915_EEPROM_BLOCK_SIZE 16
+ #define MT7915_HW_TOKEN_SIZE 4096
+ #define MT7915_TOKEN_SIZE 8192
++#define MT7915_RX_TOKEN_SIZE 4096
+
+ #define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
+ #define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
+diff --git a/tx.c b/tx.c
+index 1809b03..74bf0de 100644
+--- a/tx.c
++++ b/tx.c
+@@ -843,16 +843,16 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+ EXPORT_SYMBOL_GPL(mt76_token_consume);
+
+ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
+- struct mt76_txwi_cache *t, dma_addr_t phys)
++ struct mt76_rxwi_cache *r, dma_addr_t phys)
+ {
+ int token;
+
+ spin_lock_bh(&dev->rx_token_lock);
+- token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size,
++ token = idr_alloc(&dev->rx_token, r, 0, dev->rx_token_size,
+ GFP_ATOMIC);
+ if (token >= 0) {
+- t->ptr = ptr;
+- t->dma_addr = phys;
++ r->ptr = ptr;
++ r->dma_addr = phys;
+ }
+ spin_unlock_bh(&dev->rx_token_lock);
+
+@@ -889,15 +889,15 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
+ }
+ EXPORT_SYMBOL_GPL(mt76_token_release);
+
+-struct mt76_txwi_cache *
++struct mt76_rxwi_cache *
+ mt76_rx_token_release(struct mt76_dev *dev, int token)
+ {
+- struct mt76_txwi_cache *t;
++ struct mt76_rxwi_cache *r;
+
+ spin_lock_bh(&dev->rx_token_lock);
+- t = idr_remove(&dev->rx_token, token);
++ r = idr_remove(&dev->rx_token, token);
+ spin_unlock_bh(&dev->rx_token_lock);
+
+- return t;
++ return r;
+ }
+ EXPORT_SYMBOL_GPL(mt76_rx_token_release);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
index 21f5e83..3dc3543 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
@@ -1,8 +1,8 @@
-From 2ced3e3d33ef919332226f09a214ef2b04555a6d Mon Sep 17 00:00:00 2001
+From 1c0cb4fc09293006efdf8d1a9e92715a5705c29e Mon Sep 17 00:00:00 2001
From: "sujuan.chen" <sujuan.chen@mediatek.com>
Date: Wed, 19 Apr 2023 17:13:41 +0800
-Subject: [PATCH 2002/2008] wifi: mt76: wed: change wed token init size to
- adapt wed3.0
+Subject: [PATCH 66/98] wifi: mt76: wed: change wed token init size to adapt
+ wed3.0
Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
---
@@ -10,10 +10,10 @@
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/tx.c b/tx.c
-index 6cb71f34..618c99a1 100644
+index 74bf0de..3857c2a 100644
--- a/tx.c
+++ b/tx.c
-@@ -737,12 +737,16 @@ EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked);
+@@ -819,12 +819,16 @@ EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked);
int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
{
@@ -34,5 +34,5 @@
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-add-random-early-drop-support.patch
similarity index 82%
rename from recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-add-random-early-drop-support.patch
index 7902639..e21fa8b 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-add-random-early-drop-support.patch
@@ -1,19 +1,19 @@
-From fba98d69dcbbbcbd4cbf61e997637ecead9e55a3 Mon Sep 17 00:00:00 2001
+From 50d93c608b1cfe0750fa98c1fbafe6ad6ed3212d Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Wed, 19 Apr 2023 18:32:41 +0800
-Subject: [PATCH 2006/2008] wifi: mt76: add random early drop support
+Subject: [PATCH 67/98] wifi: mt76: add random early drop support
---
- mt7996/mcu.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++--
+ mt7996/mcu.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++--
mt7996/mcu.h | 4 ++-
mt7996/mt7996.h | 1 +
- 3 files changed, 79 insertions(+), 3 deletions(-)
+ 3 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 1891c0d7..0c01e90b 100644
+index b8d26ec..6589610 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -2933,8 +2933,8 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
+@@ -3012,8 +3012,8 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
if (ret)
return ret;
@@ -24,7 +24,7 @@
}
int mt7996_mcu_init(struct mt7996_dev *dev)
-@@ -2966,6 +2966,79 @@ out:
+@@ -3045,6 +3045,83 @@ out:
skb_queue_purge(&dev->mt76.mcu.res_q);
}
@@ -64,6 +64,10 @@
+ req.token_thr_per_src[i] = cpu_to_le16(MT7996_TOKEN_SIZE);
+ }
+
++ if (!mtk_wed_device_active(&dev->mt76.mmio.wed))
++ req.token_per_src[RED_TOKEN_SRC_CNT - 1] =
++ cpu_to_le16(MT7996_TOKEN_SIZE - MT7996_HW_TOKEN_SIZE);
++
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET),
+ &req, sizeof(req), false);
+}
@@ -105,10 +109,10 @@
{
struct {
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index a0cbf922..ec074bc6 100644
+index bb876f3..666216a 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -239,8 +239,9 @@ enum {
+@@ -287,8 +287,9 @@ enum {
enum {
MCU_WA_PARAM_PDMA_RX = 0x04,
MCU_WA_PARAM_CPU_UTIL = 0x0b,
@@ -119,7 +123,7 @@
};
enum mcu_mmps_mode {
-@@ -695,6 +696,7 @@ enum {
+@@ -817,6 +818,7 @@ enum {
UNI_VOW_DRR_CTRL,
UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
@@ -128,10 +132,10 @@
enum {
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 836c7db7..b239c44c 100644
+index 6775360..bba1364 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
-@@ -671,6 +671,7 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
+@@ -654,6 +654,7 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
@@ -140,5 +144,5 @@
int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch
deleted file mode 100644
index feb77a6..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch
+++ /dev/null
@@ -1,995 +0,0 @@
-From d9167faacb2a8466e2d19993f29b2c0770c5164e Mon Sep 17 00:00:00 2001
-From: "sujuan.chen" <sujuan.chen@mediatek.com>
-Date: Wed, 26 Apr 2023 16:44:57 +0800
-Subject: [PATCH 2003/2008] wifi: mt76: mt7996: wed: add wed3.0 tx support
-
-Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
----
- dma.c | 17 ++-
- mt76.h | 7 ++
- mt7996/dma.c | 128 ++++++++++++++++++---
- mt7996/init.c | 21 +++-
- mt7996/mac.c | 29 ++++-
- mt7996/main.c | 46 ++++++++
- mt7996/mmio.c | 295 +++++++++++++++++++++++++++++++++++++++++++++---
- mt7996/mt7996.h | 8 +-
- mt7996/pci.c | 72 +++++++++---
- mt7996/regs.h | 5 +
- 10 files changed, 567 insertions(+), 61 deletions(-)
-
-diff --git a/dma.c b/dma.c
-index 7153be47..930ec768 100644
---- a/dma.c
-+++ b/dma.c
-@@ -13,6 +13,11 @@
- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- u32 _val; \
- if ((_q)->flags & MT_QFLAG_WED) \
-+ if((_q)->flags & MT_QFLAG_WED_EXT) \
-+ _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed_ext, \
-+ ((_q)->wed_regs + \
-+ _offset)); \
-+ else \
- _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \
- ((_q)->wed_regs + \
- _offset)); \
-@@ -24,6 +29,11 @@
- #define Q_WRITE(_dev, _q, _field, _val) do { \
- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- if ((_q)->flags & MT_QFLAG_WED) \
-+ if((_q)->flags & MT_QFLAG_WED_EXT) \
-+ mtk_wed_device_reg_write(&(_dev)->mmio.wed_ext, \
-+ ((_q)->wed_regs + _offset), \
-+ _val); \
-+ else \
- mtk_wed_device_reg_write(&(_dev)->mmio.wed, \
- ((_q)->wed_regs + _offset), \
- _val); \
-@@ -654,6 +664,9 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
- if (!(q->flags & MT_QFLAG_WED))
- return 0;
-
-+ if ((q->flags & MT_QFLAG_WED_EXT))
-+ wed = &dev->mmio.wed_ext;
-+
- type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
- ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
-
-@@ -719,7 +732,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
- if (ret)
- return ret;
-
-- if (q->flags != MT_WED_Q_TXFREE)
-+ if (!mt76_queue_is_txfree(q))
- mt76_dma_queue_reset(dev, q);
-
- return 0;
-@@ -999,6 +1012,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
- if (mtk_wed_device_active(&dev->mmio.wed))
- mtk_wed_device_detach(&dev->mmio.wed);
-
-+ if (mtk_wed_device_active(&dev->mmio.wed_ext))
-+ mtk_wed_device_detach(&dev->mmio.wed_ext);
- mt76_free_pending_txwi(dev);
- mt76_free_pending_rxwi(dev);
- }
-diff --git a/mt76.h b/mt76.h
-index a0c20d36..ee0dbdd7 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -51,6 +51,7 @@
- #define MT_QFLAG_WED_RING GENMASK(1, 0)
- #define MT_QFLAG_WED_TYPE GENMASK(3, 2)
- #define MT_QFLAG_WED BIT(4)
-+#define MT_QFLAG_WED_EXT BIT(11)
-
- #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
- FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
-@@ -623,6 +624,7 @@ struct mt76_mmio {
- u32 irqmask;
-
- struct mtk_wed_device wed;
-+ struct mtk_wed_device wed_ext;
- struct completion wed_reset;
- struct completion wed_reset_complete;
- };
-@@ -1514,6 +1516,11 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
- return (q->flags & MT_QFLAG_WED) &&
- FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
- }
-+static inline bool mt76_queue_is_txfree(struct mt76_queue *q)
-+{
-+ return (q->flags & MT_QFLAG_WED) &&
-+ FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
-+}
-
- struct mt76_txwi_cache *
- mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
-diff --git a/mt7996/dma.c b/mt7996/dma.c
-index b8f253d0..673b08bb 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -7,6 +7,25 @@
- #include "../dma.h"
- #include "mac.h"
-
-+int
-+mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
-+ int ring_base, struct mtk_wed_device *wed)
-+{
-+ struct mt7996_dev *dev = phy->dev;
-+ u32 flags = 0;
-+
-+ if (mtk_wed_device_active(wed)) {
-+ ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
-+ idx -= MT_TXQ_ID(0);
-+ flags = MT_WED_Q_TX(idx);
-+ if (phy->mt76->band_idx == MT_BAND2)
-+ flags = MT_QFLAG_WED_EXT | MT_WED_Q_TX(0) ;
-+ }
-+
-+ return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc,
-+ ring_base, flags);
-+}
-+
- static int mt7996_poll_tx(struct napi_struct *napi, int budget)
- {
- struct mt7996_dev *dev;
-@@ -128,7 +147,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
- }
- }
-
--void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
-+void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
- {
- u32 hif1_ofs = 0;
- u32 irq_mask;
-@@ -153,11 +172,9 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- }
-
- /* enable interrupts for TX/RX rings */
-- irq_mask = MT_INT_MCU_CMD;
-- if (reset)
-- goto done;
--
-- irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
-+ irq_mask = MT_INT_MCU_CMD |
-+ MT_INT_RX_DONE_MCU |
-+ MT_INT_TX_DONE_MCU;
-
- if (mt7996_band_valid(dev, MT_BAND0))
- irq_mask |= MT_INT_BAND0_RX_DONE;
-@@ -168,7 +185,18 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- if (mt7996_band_valid(dev, MT_BAND2))
- irq_mask |= MT_INT_BAND2_RX_DONE;
-
--done:
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) {
-+ u32 wed_irq_mask = irq_mask;
-+
-+ wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
-+
-+ mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
-+
-+ mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
-+ }
-+
-+ irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
-+
- mt7996_irq_enable(dev, irq_mask);
- mt7996_irq_disable(dev, 0);
- }
-@@ -241,19 +269,24 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- /* fix hardware limitation, pcie1's rx ring3 is not available
- * so, redirect pcie0 rx ring3 interrupt to pcie1
- */
-- mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
-- MT_WFDMA0_RX_INT_SEL_RING3);
--
-- /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->rro_support)
-+ mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
-+ MT_WFDMA0_RX_INT_SEL_RING6);
-+ else
-+ mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
-+ MT_WFDMA0_RX_INT_SEL_RING3);
- }
-
-- __mt7996_dma_enable(dev, reset);
-+ __mt7996_dma_enable(dev, reset, true);
-
- return 0;
- }
-
- int mt7996_dma_init(struct mt7996_dev *dev)
- {
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+ struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
-+ u32 rx_base;
- u32 hif1_ofs = 0;
- int ret;
-
-@@ -267,10 +300,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- mt7996_dma_disable(dev, true);
-
- /* init tx queue */
-- ret = mt76_connac_init_tx_queues(dev->phy.mt76,
-- MT_TXQ_ID(dev->mphy.band_idx),
-- MT7996_TX_RING_SIZE,
-- MT_TXQ_RING_BASE(0), 0);
-+ ret = mt7996_init_tx_queues(&dev->phy,
-+ MT_TXQ_ID(dev->mphy.band_idx),
-+ MT7996_TX_RING_SIZE,
-+ MT_TXQ_RING_BASE(0),
-+ wed);
- if (ret)
- return ret;
-
-@@ -326,6 +360,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- return ret;
-
- /* tx free notify event from WA for band0 */
-+ if (mtk_wed_device_active(wed) && !dev->rro_support)
-+ dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
-+
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
- MT_RXQ_ID(MT_RXQ_MAIN_WA),
- MT7996_RX_MCU_RING_SIZE,
-@@ -336,17 +373,24 @@ int mt7996_dma_init(struct mt7996_dev *dev)
-
- if (mt7996_band_valid(dev, MT_BAND2)) {
- /* rx data queue for band2 */
-+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
-+ if (mtk_wed_device_active(wed))
-+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
-+
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
- MT_RXQ_ID(MT_RXQ_BAND2),
- MT7996_RX_RING_SIZE,
- MT_RX_BUF_SIZE,
-- MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs);
-+ rx_base);
- if (ret)
- return ret;
-
- /* tx free notify event from WA for band2
- * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
- */
-+ if (mtk_wed_device_active(wed_ext) && !dev->rro_support)
-+ dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE |
-+ MT_QFLAG_WED_EXT;
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2_WA],
- MT_RXQ_ID(MT_RXQ_BAND2_WA),
- MT7996_RX_MCU_RING_SIZE,
-@@ -356,6 +400,56 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- return ret;
- }
-
-+
-+ if (dev->rro_support) {
-+ /* rx rro data queue for band0 */
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags = MT_RRO_Q_DATA(0);
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_QFLAG_MAGIC;
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
-+ MT_RXQ_ID(MT_RXQ_RRO_BAND0),
-+ MT7996_RX_RING_SIZE,
-+ MT7996_RX_BUF_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0));
-+ if (ret)
-+ return ret;
-+
-+ /* tx free notify event from WA for band0 */
-+ if (mtk_wed_device_active(wed))
-+ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
-+ MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
-+ MT7996_RX_MCU_RING_SIZE,
-+ MT7996_RX_BUF_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
-+ if (ret)
-+ return ret;
-+
-+ if (mt7996_band_valid(dev, MT_BAND2)) {
-+ /* rx rro data queue for band2 */
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags = MT_RRO_Q_DATA(1);
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_QFLAG_MAGIC;
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
-+ MT_RXQ_ID(MT_RXQ_RRO_BAND2),
-+ MT7996_RX_RING_SIZE,
-+ MT7996_RX_BUF_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
-+ if (ret)
-+ return ret;
-+
-+ /* tx free notify event from MAC for band2 */
-+ if (mtk_wed_device_active(wed_ext))
-+ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE |
-+ MT_QFLAG_WED_EXT;
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2],
-+ MT_RXQ_ID(MT_RXQ_TXFREE_BAND2),
-+ MT7996_RX_MCU_RING_SIZE,
-+ MT7996_RX_BUF_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs);
-+ if (ret)
-+ return ret;
-+ }
-+ }
-+
- ret = mt76_init_queues(dev, mt76_dma_rx_poll);
- if (ret < 0)
- return ret;
-diff --git a/mt7996/init.c b/mt7996/init.c
-index a6caf4f1..6cfbc50d 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -534,6 +534,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
- struct mt76_phy *mphy;
- u32 mac_ofs, hif1_ofs = 0;
- int ret;
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-
- if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
- return 0;
-@@ -541,8 +542,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
- if (phy)
- return 0;
-
-- if (band == MT_BAND2 && dev->hif2)
-+ if (band == MT_BAND2 && dev->hif2) {
- hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-+ wed = &dev->mt76.mmio.wed_ext;
-+ }
-
- mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band);
- if (!mphy)
-@@ -576,10 +579,11 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
-
- /* init wiphy according to mphy and phy */
- mt7996_init_wiphy(mphy->hw);
-- ret = mt76_connac_init_tx_queues(phy->mt76,
-- MT_TXQ_ID(band),
-- MT7996_TX_RING_SIZE,
-- MT_TXQ_RING_BASE(band) + hif1_ofs, 0);
-+ ret = mt7996_init_tx_queues(mphy->priv,
-+ MT_TXQ_ID(band),
-+ MT7996_TX_RING_SIZE,
-+ MT_TXQ_RING_BASE(band) + hif1_ofs,
-+ wed);
- if (ret)
- goto error;
-
-@@ -1119,6 +1123,13 @@ int mt7996_register_device(struct mt7996_dev *dev)
-
- ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
-
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
-+ mt76_wr(dev, MT_INT1_MASK_CSR,
-+ dev->mt76.mmio.irqmask|MT_INT_TX_DONE_BAND2);
-+ mtk_wed_device_start(&dev->mt76.mmio.wed_ext,
-+ dev->mt76.mmio.irqmask |MT_INT_TX_DONE_BAND2);
-+ }
-+
- dev->recovery.hw_init_done = true;
-
- ret = mt7996_init_debugfs(&dev->phy);
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 993b43ce..fc2d9269 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1175,6 +1175,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- return 0;
- }
-
-+u32 mt7996_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 = BIT(31) |
-+ 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
- mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- {
-@@ -1561,6 +1584,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
-
- switch (type) {
- case PKT_TYPE_TXRX_NOTIFY:
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext) &&
-+ q == MT_RXQ_TXFREE_BAND2)
-+ return;
-+
- mt7996_mac_tx_free(dev, skb->data, skb->len);
- napi_consume_skb(skb, 1);
- break;
-@@ -2035,7 +2062,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
- mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
-
- /* enable dma tx/rx and interrupt */
-- __mt7996_dma_enable(dev, false);
-+ __mt7996_dma_enable(dev, false, false);
-
- clear_bit(MT76_MCU_RESET, &dev->mphy.state);
- clear_bit(MT76_RESET, &dev->mphy.state);
-diff --git a/mt7996/main.c b/mt7996/main.c
-index f0bdec6b..50fa6523 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -1405,6 +1405,49 @@ out:
- return ret;
- }
-
-+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+static int
-+mt7996_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 mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
-+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+
-+ if(phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
-+ wed = &dev->mt76.mmio.wed_ext;
-+
-+ if (!mtk_wed_device_active(wed))
-+ return -ENODEV;
-+
-+ if (msta->wcid.idx > MT7996_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.queue = 0;
-+ path->mtk_wdma.wcid = msta->wcid.idx;
-+
-+ /* pao info */
-+ if (mtk_wed_device_support_pao(wed)) {
-+ path->mtk_wdma.amsdu_en = 1;
-+ path->mtk_wdma.is_sp = 0;
-+ path->mtk_wdma.is_fixedrate = 0;
-+ }
-+ ctx->dev = NULL;
-+
-+ return 0;
-+}
-+
-+#endif
-+
- const struct ieee80211_ops mt7996_ops = {
- .tx = mt7996_tx,
- .start = mt7996_start,
-@@ -1451,4 +1494,7 @@ const struct ieee80211_ops mt7996_ops = {
- .sta_add_debugfs = mt7996_sta_add_debugfs,
- #endif
- .set_radar_background = mt7996_set_radar_background,
-+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+ .net_fill_forward_path = mt7996_net_fill_forward_path,
-+#endif
- };
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 3a591a7b..b9e47e73 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -10,6 +10,11 @@
- #include "mt7996.h"
- #include "mac.h"
- #include "../trace.h"
-+#include "../dma.h"
-+
-+
-+static bool wed_enable = true;
-+module_param(wed_enable, bool, 0644);
-
- static const struct __base mt7996_reg_base[] = {
- [WF_AGG_BASE] = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
-@@ -191,6 +196,228 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
- return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
- }
-
-+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+static void mt7996_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
-+{
-+ struct mt7996_dev *dev;
-+ struct page *page;
-+ int i;
-+
-+ dev = container_of(wed, struct mt7996_dev, mt76.mmio.wed);
-+ for (i = 0; i < dev->mt76.rx_token_size; i++) {
-+ struct mt76_rxwi_cache *r;
-+
-+ r = mt76_rx_token_release(&dev->mt76, i);
-+ if (!r || !r->ptr)
-+ continue;
-+
-+ dma_unmap_single(dev->mt76.dma_dev, r->dma_addr,
-+ wed->wlan.rx_size, DMA_FROM_DEVICE);
-+ skb_free_frag(r->ptr);
-+ r->ptr = NULL;
-+
-+ mt76_put_rxwi(&dev->mt76, r);
-+ }
-+
-+ mt76_free_pending_rxwi(&dev->mt76);
-+
-+ mt76_for_each_q_rx(&dev->mt76, i) {
-+ struct mt76_queue *q = &dev->mt76.q_rx[i];
-+
-+ if (mt76_queue_is_wed_rx(q)) {
-+ if (!q->rx_page.va)
-+ continue;
-+
-+ page = virt_to_page(q->rx_page.va);
-+ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
-+ memset(&q->rx_page, 0, sizeof(q->rx_page));
-+ }
-+ }
-+
-+ if (!wed->rx_buf_ring.rx_page.va)
-+ return;
-+
-+ page = virt_to_page(wed->rx_buf_ring.rx_page.va);
-+ __page_frag_cache_drain(page, wed->rx_buf_ring.rx_page.pagecnt_bias);
-+ memset(&wed->rx_buf_ring.rx_page, 0, sizeof(wed->rx_buf_ring.rx_page));
-+
-+}
-+
-+static u32 mt7996_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
-+{
-+ struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
-+ struct mt7996_dev *dev;
-+ u32 length;
-+ int i;
-+
-+ dev = container_of(wed, struct mt7996_dev, mt76.mmio.wed);
-+ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
-+ sizeof(struct skb_shared_info));
-+
-+ for (i = 0; i < size; i++) {
-+ struct mt76_rxwi_cache *r = mt76_get_rxwi(&dev->mt76);
-+ dma_addr_t phy_addr;
-+ int token;
-+ void *ptr;
-+
-+ ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length,
-+ GFP_KERNEL);
-+ if (!ptr) {
-+ mt76_put_rxwi(&dev->mt76, r);
-+ goto unmap;
-+ }
-+
-+ phy_addr = dma_map_single(dev->mt76.dma_dev, ptr,
-+ wed->wlan.rx_size,
-+ DMA_TO_DEVICE);
-+ if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
-+ skb_free_frag(ptr);
-+ mt76_put_rxwi(&dev->mt76, r);
-+ goto unmap;
-+ }
-+
-+ desc->buf0 = cpu_to_le32(phy_addr);
-+ token = mt76_rx_token_consume(&dev->mt76, ptr, r, phy_addr);
-+ if (token < 0) {
-+ dma_unmap_single(dev->mt76.dma_dev, phy_addr,
-+ wed->wlan.rx_size, DMA_TO_DEVICE);
-+ skb_free_frag(ptr);
-+ mt76_put_rxwi(&dev->mt76, r);
-+ goto unmap;
-+ }
-+
-+ desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
-+ token));
-+ desc++;
-+ }
-+
-+ return 0;
-+
-+unmap:
-+ mt7996_mmio_wed_release_rx_buf(wed);
-+ return -ENOMEM;
-+}
-+#endif
-+
-+int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
-+ bool hif2, int *irq)
-+{
-+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+ struct pci_dev *pci_dev = pdev_ptr;
-+ u32 hif1_ofs = 0;
-+ int ret;
-+
-+ if (!wed_enable)
-+ return 0;
-+
-+ dev->rro_support = true;
-+
-+ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-+
-+ if (hif2)
-+ wed = &dev->mt76.mmio.wed_ext;
-+
-+ wed->wlan.pci_dev = pci_dev;
-+ wed->wlan.bus_type = MTK_WED_BUS_PCIE;
-+
-+ wed->wlan.base = devm_ioremap(dev->mt76.dev,
-+ pci_resource_start(pci_dev, 0),
-+ pci_resource_len(pci_dev, 0));
-+ wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
-+
-+ if (hif2) {
-+ wed->wlan.wpdma_int = wed->wlan.phy_base +
-+ MT_INT_PCIE1_SOURCE_CSR_EXT;
-+ wed->wlan.wpdma_mask = wed->wlan.phy_base +
-+ MT_INT_PCIE1_MASK_CSR;
-+ wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
-+ MT_TXQ_RING_BASE(0) +
-+ MT7996_TXQ_BAND2 * MT_RING_SIZE;
-+ if (dev->rro_support) {
-+ wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
-+ MT_RXQ_RING_BASE(0) +
-+ MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
-+ wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
-+ } else {
-+ wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
-+ MT_RXQ_RING_BASE(0) +
-+ MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
-+ wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
-+ }
-+
-+ wed->wlan.chip_id = 0x7991;
-+ wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
-+ } else {
-+ wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
-+ wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
-+ wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
-+ MT7996_TXQ_BAND0 * MT_RING_SIZE;
-+
-+ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
-+
-+ wed->wlan.wpdma_rx = wed->wlan.phy_base +
-+ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
-+ MT7996_RXQ_BAND0 * MT_RING_SIZE;
-+
-+ wed->wlan.rx_nbuf = 65536;
-+ wed->wlan.rx_npkt = 24576;
-+ wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
-+
-+ wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
-+ wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
-+
-+ wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
-+ wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
-+ if (dev->rro_support) {
-+ wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
-+ MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
-+ wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
-+ } else {
-+ wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
-+ wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
-+ MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
-+ }
-+ }
-+
-+ wed->wlan.nbuf = 16384;
-+
-+ wed->wlan.token_start = 0;
-+
-+ wed->wlan.max_amsdu_nums = 8;
-+ wed->wlan.max_amsdu_len = 1536;
-+
-+ wed->wlan.init_buf = mt7996_wed_init_buf;
-+ wed->wlan.offload_enable = NULL;
-+ wed->wlan.offload_disable = NULL;
-+ wed->wlan.init_rx_buf = mt7996_mmio_wed_init_rx_buf;
-+ wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
-+ wed->wlan.update_wo_rx_stats = NULL;
-+
-+ dev->mt76.rx_token_size += wed->wlan.rx_npkt;
-+
-+ if (mtk_wed_device_attach(wed))
-+ return 0;
-+
-+ *irq = wed->irq;
-+ dev->mt76.dma_dev = wed->dev;
-+
-+ dev->mt76.token_size = 1024;
-+
-+ ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
-+ if (ret)
-+ return ret;
-+
-+ ret = dma_set_coherent_mask(wed->dev, DMA_BIT_MASK(32));
-+ if (ret)
-+ return ret;
-+
-+ return 1;
-+#else
-+ return 0;
-+#endif
-+}
-+
- static int mt7996_mmio_init(struct mt76_dev *mdev,
- void __iomem *mem_base,
- u32 device_id)
-@@ -241,8 +468,17 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
- mdev->mmio.irqmask |= set;
-
- if (write_reg) {
-- mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
-- mt76_wr(dev, MT_INT1_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);
-+ if (mtk_wed_device_active(&mdev->mmio.wed_ext)) {
-+ mtk_wed_device_irq_set_mask(&mdev->mmio.wed_ext,
-+ mdev->mmio.irqmask);
-+ }
-+ } else {
-+ mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
-+ mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
-+ }
- }
-
- spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
-@@ -260,22 +496,36 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
- static void mt7996_irq_tasklet(struct tasklet_struct *t)
- {
- struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+ struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
- u32 i, intr, mask, intr1;
-
-- 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);
--
-- if (dev->hif2) {
-- intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
-- intr1 &= dev->mt76.mmio.irqmask;
-- mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
-+ if (dev->hif2 && mtk_wed_device_active(wed_ext)) {
-+ mtk_wed_device_irq_set_mask(wed_ext, 0);
-+ intr1 = mtk_wed_device_irq_get(wed_ext,
-+ dev->mt76.mmio.irqmask);
-+ if (intr1 & MT_INT_RX_TXFREE_EXT)
-+ napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
-+ }
-
-- intr |= intr1;
-+ 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);
-+ intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
-+ } else {
-+ 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);
-+ if (dev->hif2) {
-+ intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
-+ intr1 &= dev->mt76.mmio.irqmask;
-+ mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
-+ intr |= intr1;
-+ }
- }
-
- trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
-@@ -307,10 +557,19 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
- irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
- {
- struct mt7996_dev *dev = dev_instance;
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-+ 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) {
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
-+ mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_ext, 0);
-+ else
-+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-+ }
-
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
- return IRQ_NONE;
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index e371964b..43f20da4 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -544,7 +544,9 @@ int mt7996_dma_init(struct mt7996_dev *dev);
- void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
- void mt7996_dma_prefetch(struct mt7996_dev *dev);
- void mt7996_dma_cleanup(struct mt7996_dev *dev);
--void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset);
-+int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
-+ int n_desc, int ring_base, struct mtk_wed_device *wed);
-+void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset);
- void mt7996_init_txpower(struct mt7996_dev *dev,
- struct ieee80211_supported_band *sband);
- int mt7996_txbf_init(struct mt7996_dev *dev);
-@@ -732,7 +734,9 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
- void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct dentry *dir);
- #endif
--
-+int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
-+ bool hif2, int *irq);
-+u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
- #ifdef CONFIG_MTK_VENDOR
- void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
- void mt7996_vendor_register(struct mt7996_phy *phy);
-diff --git a/mt7996/pci.c b/mt7996/pci.c
-index c5301050..869f32ac 100644
---- a/mt7996/pci.c
-+++ b/mt7996/pci.c
-@@ -125,15 +125,26 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
- mt7996_wfsys_reset(dev);
- hif2 = mt7996_pci_init_hif2(pdev);
-
-- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
-+ ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
- if (ret < 0)
-- goto free_device;
-+ goto free_wed_or_irq_vector;
-
-- irq = pdev->irq;
-- ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
-+ if (!ret) {
-+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
-+ if (ret < 0)
-+ goto free_device;
-+ }
-+ ret = devm_request_irq(mdev->dev, pdev->irq, mt7996_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
- if (ret)
-- goto free_irq_vector;
-+ goto free_wed_or_irq_vector;
-+
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-+ ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
-+ IRQF_SHARED, KBUILD_MODNAME "-wed", dev);
-+ if (ret)
-+ goto free_irq;
-+ }
-
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
- /* master switch of PCIe tnterrupt enable */
-@@ -143,16 +154,30 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
- hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
- dev->hif2 = hif2;
-
-- ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
-+ ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &irq);
- if (ret < 0)
-- goto free_hif2;
-+ goto free_irq;
-+
-+ if (!ret) {
-+ ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
-+ if (ret < 0)
-+ goto free_hif2;
-
-- dev->hif2->irq = hif2_dev->irq;
-- ret = devm_request_irq(mdev->dev, dev->hif2->irq,
-- mt7996_irq_handler, IRQF_SHARED,
-- KBUILD_MODNAME "-hif", dev);
-+ dev->hif2->irq = hif2_dev->irq;
-+ }
-+
-+ ret = devm_request_irq(mdev->dev, hif2_dev->irq, mt7996_irq_handler,
-+ IRQF_SHARED, KBUILD_MODNAME "-hif", dev);
- if (ret)
-- goto free_hif2_irq_vector;
-+ goto free_hif2;
-+
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
-+ ret = devm_request_irq(mdev->dev, irq,
-+ mt7996_irq_handler, IRQF_SHARED,
-+ KBUILD_MODNAME "-wed-hif", dev);
-+ if (ret)
-+ goto free_hif2_irq_vector;
-+ }
-
- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
- /* master switch of PCIe tnterrupt enable */
-@@ -168,15 +193,28 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
- free_hif2_irq:
- if (dev->hif2)
- devm_free_irq(mdev->dev, dev->hif2->irq, dev);
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
-+ devm_free_irq(mdev->dev, dev->mt76.mmio.wed_ext.irq, dev);
- free_hif2_irq_vector:
-- if (dev->hif2)
-- pci_free_irq_vectors(hif2_dev);
-+ if (dev->hif2) {
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
-+ mtk_wed_device_detach(&dev->mt76.mmio.wed_ext);
-+ else
-+ pci_free_irq_vectors(hif2_dev);
-+ }
- free_hif2:
- if (dev->hif2)
- put_device(dev->hif2->dev);
-- devm_free_irq(mdev->dev, irq, dev);
--free_irq_vector:
-- pci_free_irq_vectors(pdev);
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
-+ devm_free_irq(mdev->dev, dev->mt76.mmio.wed.irq, dev);
-+free_irq:
-+ devm_free_irq(mdev->dev, pdev->irq, dev);
-+free_wed_or_irq_vector:
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
-+ mtk_wed_device_detach(&dev->mt76.mmio.wed);
-+ else
-+ pci_free_irq_vectors(pdev);
-+
- free_device:
- mt76_free_device(&dev->mt76);
-
-diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 6ef905a9..04658639 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -323,6 +323,7 @@ enum base_rev {
-
- #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
- #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
-+#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)
-
- #define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
-
-@@ -367,6 +368,9 @@ enum base_rev {
- #define MT_WFDMA0_PCIE1_BASE 0xd8000
- #define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
-
-+#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118)
-+#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c)
-+
- #define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)
- #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0)
- #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
-@@ -412,6 +416,7 @@ enum base_rev {
- #define MT_INT_RX_TXFREE_MAIN BIT(17)
- #define MT_INT_RX_TXFREE_TRI BIT(15)
- #define MT_INT_MCU_CMD BIT(29)
-+#define MT_INT_RX_TXFREE_EXT BIT(26)
-
- #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
- #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
new file mode 100644
index 0000000..d9fe625
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
@@ -0,0 +1,425 @@
+From d663fd304a7bd5701b2b3ac42b4743dabb252750 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 18 May 2023 15:01:47 +0800
+Subject: [PATCH 68/98] wifi: mt76: mt7996: reset addr_elem when delete ba
+
+The old addr element info may be used when the signature is not equel to
+0xff, and sta will find error SDP cause the SDP/SDL=0 issue.
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt76.h | 1 +
+ mt76_connac_mcu.h | 1 +
+ mt7996/init.c | 3 ++
+ mt7996/mac.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c | 77 +++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h | 46 ++++++++++++++++++++++
+ mt7996/mt7996.h | 27 +++++++++++++
+ mt7996/regs.h | 6 +++
+ 8 files changed, 258 insertions(+)
+
+diff --git a/mt76.h b/mt76.h
+index b960f3d..bea58ff 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -434,6 +434,7 @@ struct mt76_rx_tid {
+ u16 nframes;
+
+ u8 num;
++ u16 session_id;
+
+ u8 started:1, stopped:1, timer_pending:1;
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index e904ebc..f659d2e 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1038,6 +1038,7 @@ enum {
+ MCU_UNI_EVENT_THERMAL = 0x35,
+ MCU_UNI_EVENT_NIC_CAPAB = 0x43,
+ MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
++ MCU_UNI_EVENT_RRO = 0x57,
+ MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
+ MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
+ };
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 4503482..1f01f24 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -779,6 +779,9 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
+ mt76_wr(dev, MT_RRO_HOST_INT_ENA,
+ MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
+
++ INIT_WORK(&dev->wed_rro.rro_del_work, mt7996_rro_delete_sessions);
++ INIT_LIST_HEAD(&dev->wed_rro.rro_poll_list);
++
+ /* rro ind cmd queue init */
+ return mt7996_dma_rro_init(dev);
+ #else
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index b24f237..60ca23b 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1450,6 +1450,96 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ }
+ }
+
++static struct mt7996_wed_rro_addr *
++mt7996_rro_get_addr_elem(struct mt7996_dev *dev, u16 seid, u16 sn)
++{
++ u32 idx;
++ void *addr;
++
++ if (seid == MT7996_RRO_MAX_SESSION) {
++ addr = dev->wed_rro.session.ptr;
++ idx = sn % MT7996_RRO_WINDOW_MAX_LEN;
++ } else {
++ addr = dev->wed_rro.addr_elem[seid / MT7996_RRO_BA_BITMAP_SESSION_SIZE].ptr;
++ idx = (seid % MT7996_RRO_BA_BITMAP_SESSION_SIZE) * MT7996_RRO_WINDOW_MAX_LEN
++ + (sn % MT7996_RRO_WINDOW_MAX_LEN);
++ }
++ return addr + idx * sizeof(struct mt7996_wed_rro_addr);
++}
++
++static bool mt7996_rro_reset_sessions(struct mt7996_dev *dev, u16 session_id)
++{
++ struct mt7996_wed_rro_addr *elem;
++ int i;
++
++ for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
++ elem = mt7996_rro_get_addr_elem(dev, session_id, i);
++ elem->signature = 0xff;
++ }
++ return true;
++
++}
++
++void mt7996_rro_delete_sessions(struct work_struct *work)
++{
++ struct mt7996_dev *dev;
++ struct mt7996_rro_ba_session_elem *e;
++ int elem_nums;
++ LIST_HEAD(rro_poll_list);
++
++ dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
++ wed_rro.rro_del_work);
++ elem_nums = dev->wed_rro.elem_nums;
++
++ spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++ list_splice_init(&dev->wed_rro.rro_poll_list, &rro_poll_list);
++ spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++
++ do {
++ spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++ if (list_empty(&rro_poll_list)) {
++ spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++ break;
++ }
++
++ e = list_first_entry(&rro_poll_list,
++ struct mt7996_rro_ba_session_elem,
++ poll_list);
++ if (!e) {
++ spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++ break;
++ }
++ list_del_init(&e->poll_list);
++ spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++
++ if (mt7996_rro_reset_sessions(dev, e->session_id)) {
++ mt7996_mcu_reset_rro_sessions(dev, e->session_id);
++ kfree(e);
++ dev->wed_rro.elem_nums--;
++ }
++ elem_nums--;
++ } while (elem_nums);
++}
++
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev, u16 seid)
++{
++ struct mt7996_rro_ba_session_elem *e;
++
++ e = kzalloc(sizeof(*e), GFP_ATOMIC);
++ if (!e)
++ return -ENOMEM;
++
++ e->session_id = seid;
++
++ spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++ list_add_tail(&e->poll_list, &dev->wed_rro.rro_poll_list);
++ spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++ dev->wed_rro.elem_nums++;
++
++ ieee80211_queue_work(mt76_hw(dev), &dev->wed_rro.rro_del_work);
++ return 0;
++}
++
+ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
+ {
+ struct mt7996_dev *dev = phy->dev;
+@@ -1774,6 +1864,9 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ if (phy3)
+ ieee80211_stop_queues(phy3->mt76->hw);
+
++ if (dev->has_rro)
++ cancel_work_sync(&dev->wed_rro.rro_del_work);
++
+ cancel_delayed_work_sync(&dev->mphy.mac_work);
+ if (phy2)
+ cancel_delayed_work_sync(&phy2->mt76->mac_work);
+@@ -1865,6 +1958,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ set_bit(MT76_RESET, &dev->mphy.state);
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ wake_up(&dev->mt76.mcu.wait);
++
++ if (dev->has_rro)
++ cancel_work_sync(&dev->wed_rro.rro_del_work);
++
+ cancel_delayed_work_sync(&dev->mphy.mac_work);
+ if (phy2) {
+ set_bit(MT76_RESET, &phy2->mt76->state);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6589610..ce38a5e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -538,6 +538,60 @@ mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rat
+ return 0;
+ }
+
++static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++ struct mt7996_mcu_rro_event *event;
++ struct mt7996_mcu_rro_ba *rro;
++ struct mt7996_mcu_rro_ba_del_chk_done *delba;
++ u16 len;
++
++ if (!dev->has_rro)
++ return;
++
++ event = (struct mt7996_mcu_rro_event *)skb->data;
++ skb_pull(skb, sizeof(struct mt7996_mcu_rxd) + 4);
++
++ switch (event->tag) {
++ case UNI_RRO_BA_SESSION_STATUS: {
++ len = sizeof(struct mt7996_mcu_rro_ba);
++ while (unlikely(len > skb->len) ? NULL : true) {
++ rro = (struct mt7996_mcu_rro_ba *)skb->data;
++ u16 idx = cpu_to_le16(rro->wlan_id);
++ struct mt76_rx_tid *tid;
++ struct mt76_wcid *wcid;
++
++ wcid = rcu_dereference(dev->mt76.wcid[idx]);
++ if (!wcid || !wcid->sta)
++ return;
++
++ tid = rcu_dereference(wcid->aggr[rro->tid]);
++ if (!tid)
++ return;
++ tid->session_id = cpu_to_le16(rro->session_id);
++ skb_pull(skb, len);
++ }
++ break;
++ }
++ case UNI_RRO_BA_SESSION_DEL_CHK_DONE: {
++ len = sizeof(struct mt7996_mcu_rro_ba_del_chk_done);
++ while (unlikely(len > skb->len) ? NULL : true) {
++ delba = (struct mt7996_mcu_rro_ba_del_chk_done *)skb->data;
++ u16 session_id = cpu_to_le16(delba->session_id);
++
++ mt7996_rro_add_delete_elem(dev, session_id);
++ skb_pull(skb, len);
++ }
++ break;
++ }
++
++ default:
++ dev_info(dev->mt76.dev, "%s: unknown rro event tag %d\n",
++ __func__, event->tag);
++ break;
++ }
++
++}
++
+ static void
+ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -663,6 +717,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ mt7996_tm_rf_test_event(dev, skb);
+ break;
+ #endif
++ case MCU_UNI_EVENT_RRO:
++ mt7996_mcu_rx_rro(dev, skb);
++ break;
+ default:
+ break;
+ }
+@@ -4615,6 +4672,26 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ sizeof(req), true);
+ }
+
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev, u16 seid)
++{
++ struct {
++ /* fixed field */
++ u8 __rsv[4];
++
++ __le16 tag;
++ __le16 len;
++ __le16 session_id;
++ u8 pad[4];
++ } __packed req = {
++ .tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .session_id = cpu_to_le16(seid),
++ };
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO),
++ &req, sizeof(req), true);
++}
++
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+ {
+ struct mt7996_dev *dev = phy->dev;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 666216a..0aa68f7 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -239,6 +239,50 @@ struct mt7996_mcu_all_sta_info_event {
+ };
+ } __packed;
+
++struct mt7996_mcu_rro_event {
++ struct mt7996_mcu_rxd rxd;
++
++ u8 __rsv1[4];
++
++ __le16 tag;
++ __le16 len;
++} __packed;
++
++struct mt7996_mcu_rro_ba {
++ __le16 tag;
++ __le16 len;
++
++ __le16 wlan_id;
++ u8 tid;
++ u8 __rsv1;
++ __le32 status;
++ __le16 session_id;
++ u8 __rsv2[2];
++} __packed;
++
++struct mt7996_mcu_rro_ba_del_chk_done {
++ __le16 tag;
++ __le16 len;
++
++ __le16 session_id;
++ u8 __rsv2[2];
++} __packed;
++
++enum {
++ UNI_RRO_BA_SESSION_STATUS = 0,
++ UNI_RRO_BA_SESSION_TBL = 1,
++ UNI_RRO_BA_SESSION_DEL_CHK_DONE = 2,
++ UNI_RRO_BA_SESSION_MAX_NUM
++};
++
++struct mt7996_mcu_rro_del_ba {
++ struct mt7996_mcu_rro_event event;
++
++ u8 wlan_idx;
++ u8 tid;
++ u8 __rsv2[2];
++};
++
+ enum mt7996_chan_mib_offs {
+ UNI_MIB_OBSS_AIRTIME = 26,
+ UNI_MIB_NON_WIFI_TIME = 27,
+@@ -840,6 +884,8 @@ enum {
+ UNI_RRO_GET_BA_SESSION_TABLE,
+ UNI_RRO_SET_BYPASS_MODE,
+ UNI_RRO_SET_TXFREE_PATH,
++ UNI_RRO_DEL_BA_SESSION,
++ UNI_RRO_SET_FLUSH_TIMEOUT
+ };
+
+ enum{
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index bba1364..af67c59 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -282,6 +282,26 @@ struct mt7996_wed_rro_addr {
+ u32 signature : 8;
+ };
+
++struct mt7996_rro_ba_session {
++ u32 ack_sn :12;
++ u32 win_sz :3;
++ u32 bn :1;
++ u32 last_in_sn :12;
++ u32 bc :1;
++ u32 bd :1;
++ u32 sat :1;
++ u32 cn :1;
++ u32 within_cnt :12;
++ u32 to_sel :3;
++ u32 rsv :1;
++ u32 last_in_rxtime :12;
++};
++
++struct mt7996_rro_ba_session_elem {
++ struct list_head poll_list;
++ u16 session_id;
++};
++
+ struct mt7996_phy {
+ struct mt76_phy *mt76;
+ struct mt7996_dev *dev;
+@@ -418,6 +438,10 @@ struct mt7996_dev {
+ void *ptr;
+ dma_addr_t phy_addr;
+ } session;
++ struct work_struct rro_del_work;
++ spinlock_t rro_stbl_lock;
++ struct list_head rro_poll_list;
++ u16 elem_nums;
+ } wed_rro;
+
+ bool testmode_enable;
+@@ -653,6 +677,7 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev, u16 seid);
+ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
+ int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
+ int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
+@@ -757,6 +782,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct ieee80211_sta *sta,
+ struct mt76_tx_info *tx_info);
+ void mt7996_tx_token_put(struct mt7996_dev *dev);
++void mt7996_rro_delete_sessions(struct work_struct *work);
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev, u16 seid);
+ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ struct sk_buff *skb, u32 *info);
+ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index d305c25..38467d9 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -101,6 +101,12 @@ enum offs_rev {
+ #define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
+ #define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
+
++#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0)
++#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0)
++#define MT_RRO_DBG_RD_EXEC BIT(31)
++
++#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + _n * 0x4)
++
+ #define MT_MCU_INT_EVENT 0x2108
+ #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
+ #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch
deleted file mode 100644
index 9a003d7..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch
+++ /dev/null
@@ -1,1471 +0,0 @@
-From 017ed7925cbdfb41d3d85fed54a97cff9fcf2f78 Mon Sep 17 00:00:00 2001
-From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Mon, 6 Feb 2023 13:50:56 +0800
-Subject: [PATCH] wifi: mt76: mt7996: wed: add wed3.0 rx support
-
-add hardware rro support, This is the preliminary patch for WED3.0 support.
-
-Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
-Change-Id: I7e113b1392bcf085ec02c8a44ffbb7cf7c3fa027
-Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
----
- dma.c | 205 +++++++++++++++++++++++++++++++++++++-----------
- dma.h | 12 +++
- mac80211.c | 1 +
- mt76.h | 63 +++++++++++++--
- mt7996/dma.c | 163 ++++++++++++++++++++++++++++++++------
- mt7996/init.c | 124 ++++++++++++++++++++++++++++-
- mt7996/mac.c | 42 ++++++++--
- mt7996/mcu.c | 8 +-
- mt7996/mmio.c | 36 +++++++--
- mt7996/mt7996.h | 58 ++++++++++++++
- mt7996/regs.h | 63 ++++++++++++++-
- 11 files changed, 683 insertions(+), 92 deletions(-)
-
-diff --git a/dma.c b/dma.c
-index 930ec768..e5b4d898 100644
---- a/dma.c
-+++ b/dma.c
-@@ -193,46 +193,68 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
- static void
- mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
- {
-+ int ndesc = q->ndesc;
-+
-+ if (q->flags & MT_QFLAG_MAGIC)
-+ ndesc |= MT_DMA_MAGIC_EN;
-+
- Q_WRITE(dev, q, desc_base, q->desc_dma);
-- Q_WRITE(dev, q, ring_size, q->ndesc);
-+ Q_WRITE(dev, q, ring_size, ndesc);
- q->head = Q_READ(dev, q, dma_idx);
- q->tail = q->head;
- }
-
- static void
--mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
-+mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, bool skip)
- {
- int i;
-
- if (!q || !q->ndesc)
- return;
-
-+ if (!q->desc)
-+ goto done;
-+
- /* clear descriptors */
- for (i = 0; i < q->ndesc; i++)
- q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
-
-+ if (skip)
-+ goto sync;
-+
-+done:
- Q_WRITE(dev, q, cpu_idx, 0);
- Q_WRITE(dev, q, dma_idx, 0);
-+sync:
- mt76_dma_sync_idx(dev, q);
- }
-
- static int
- mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
-- struct mt76_queue_buf *buf, void *data)
-+ struct mt76_queue_buf *buf, void *data,
-+ struct mt76_rxwi_cache *rxwi)
- {
-- struct mt76_desc *desc = &q->desc[q->head];
-+ struct mt76_desc *desc;
- struct mt76_queue_entry *entry = &q->entry[q->head];
-- struct mt76_rxwi_cache *rxwi = NULL;
- u32 buf1 = 0, ctrl;
- int idx = q->head;
- int rx_token;
-+ void *e_buf = data;
-+
-+ if (mt76_queue_is_rro_ind(q)) {
-+ e_buf = &q->rro_desc[q->head];
-+ goto done;
-+ }
-
-+ desc = &q->desc[q->head];
- ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
-
- if (mt76_queue_is_wed_rx(q)) {
-- rxwi = mt76_get_rxwi(dev);
-- if (!rxwi)
-- return -ENOMEM;
-+ if (!rxwi) {
-+ rxwi = mt76_get_rxwi(dev);
-+ if (!rxwi)
-+ return -ENOMEM;
-+ }
-
- rx_token = mt76_rx_token_consume(dev, data, rxwi, buf->addr);
- if (rx_token < 0) {
-@@ -249,10 +271,11 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
- WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
- WRITE_ONCE(desc->info, 0);
-
-+done:
- entry->dma_addr[0] = buf->addr;
- entry->dma_len[0] = buf->len;
- entry->rxwi = rxwi;
-- entry->buf = data;
-+ entry->buf = e_buf;
- entry->wcid = 0xffff;
- entry->skip_buf1 = true;
- q->head = (q->head + 1) % q->ndesc;
-@@ -396,14 +419,18 @@ 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, bool *drop)
-+ int *len, u32 *info, bool *more, bool *drop, bool flush)
- {
- struct mt76_queue_entry *e = &q->entry[idx];
- struct mt76_desc *desc = &q->desc[idx];
-- void *buf;
-+ void *buf = e->buf;
-+ u32 ctrl;
-
-+ if (mt76_queue_is_rro_ind(q))
-+ goto done;
-+
-+ ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
- if (len) {
-- u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
- *len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
- *more = !(ctrl & MT_DMA_CTL_LAST_SEC0);
- }
-@@ -411,6 +438,12 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- if (info)
- *info = le32_to_cpu(desc->info);
-
-+ if (drop) {
-+ *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
-+ if (ctrl & MT_DMA_CTL_VER_MASK)
-+ *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
-+ }
-+
- if (mt76_queue_is_wed_rx(q)) {
- u32 buf1 = le32_to_cpu(desc->buf1);
- u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
-@@ -423,28 +456,54 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- SKB_WITH_OVERHEAD(q->buf_size),
- DMA_FROM_DEVICE);
-
-- buf = r->ptr;
-- r->dma_addr = 0;
-- r->ptr = NULL;
--
-- mt76_put_rxwi(dev, r);
--
-- if (drop) {
-- u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
--
-- *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
-- MT_DMA_CTL_DROP));
-+ if (flush) {
-+ buf = r->ptr;
-+ r->dma_addr = 0;
-+ r->ptr = NULL;
-+
-+ mt76_put_rxwi(dev, r);
-+ } else {
-+ struct mt76_queue_buf qbuf;
-+
-+ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
-+ if (!buf)
-+ return NULL;
-+
-+ memcpy(buf, r->ptr, SKB_WITH_OVERHEAD(q->buf_size));
-+
-+ r->dma_addr = dma_map_single(dev->dma_dev, r->ptr,
-+ SKB_WITH_OVERHEAD(q->buf_size),
-+ DMA_FROM_DEVICE);
-+ if (unlikely(dma_mapping_error(dev->dma_dev, r->dma_addr))) {
-+ skb_free_frag(r->ptr);
-+ mt76_put_rxwi(dev, r);
-+ return NULL;
-+ }
-+
-+ qbuf.addr = r->dma_addr;
-+ qbuf.len = SKB_WITH_OVERHEAD(q->buf_size);
-+ qbuf.skip_unmap = false;
-+
-+ if (mt76_dma_add_rx_buf(dev, q, &qbuf, r->ptr, r) < 0) {
-+ dma_unmap_single(dev->dma_dev, r->dma_addr,
-+ SKB_WITH_OVERHEAD(q->buf_size),
-+ DMA_FROM_DEVICE);
-+ skb_free_frag(r->ptr);
-+ mt76_put_rxwi(dev, r);
-+ return NULL;
-+ }
-+ }
-
-+ if (drop)
- *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
-- }
- } else {
-- buf = e->buf;
-- e->buf = NULL;
- dma_unmap_single(dev->dma_dev, e->dma_addr[0],
- SKB_WITH_OVERHEAD(q->buf_size),
- DMA_FROM_DEVICE);
- }
-
-+done:
-+ e->buf = NULL;
- return buf;
- }
-
-@@ -458,15 +517,22 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
- if (!q->queued)
- return NULL;
-
-- if (flush)
-- q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
-- else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
-+ if (mt76_queue_is_rro_ind(q)) {
-+ goto done;
-+ } else if (q->flags & MT_QFLAG_RRO) {
- return NULL;
-+ } else {
-+ if (flush)
-+ q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
-+ else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
-+ return NULL;
-+ }
-
-+done:
- q->tail = (q->tail + 1) % q->ndesc;
- q->queued--;
-
-- return mt76_dma_get_buf(dev, q, idx, len, info, more, drop);
-+ return mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);
- }
-
- static int
-@@ -615,7 +681,10 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
-
- while (q->queued < q->ndesc - 1) {
- struct mt76_queue_buf qbuf;
-- void *buf;
-+ void *buf = NULL;
-+
-+ if (mt76_queue_is_rro_ind(q))
-+ goto done;
-
- buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
- if (!buf)
-@@ -627,10 +696,11 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
- break;
- }
-
-+done:
- qbuf.addr = addr + offset;
- qbuf.len = len - offset;
- qbuf.skip_unmap = false;
-- if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
-+ if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf, NULL) < 0) {
- dma_unmap_single(dev->dma_dev, addr, len,
- DMA_FROM_DEVICE);
- skb_free_frag(buf);
-@@ -639,7 +709,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
- frames++;
- }
-
-- if (frames)
-+ if (frames || mt76_queue_is_wed_rx(q))
- mt76_dma_kick_queue(dev, q);
-
- spin_unlock_bh(&q->lock);
-@@ -652,7 +722,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- struct mtk_wed_device *wed = &dev->mmio.wed;
- int ret, type, ring;
-- u8 flags;
-+ u16 flags;
-
- if (!q || !q->ndesc)
- return -EINVAL;
-@@ -679,7 +749,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
- 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_queue_reset(dev, q, false);
- mt76_dma_rx_fill(dev, q);
- q->flags = flags;
-
-@@ -688,9 +758,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
- 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, reset);
-- if (!ret)
-- q->wed_regs = wed->rx_ring[ring].reg_base;
-+ if (q->flags & MT_QFLAG_RRO) {
-+ q->flags &= ~0x1f;
-+
-+ ring = FIELD_GET(MT_QFLAG_RRO_RING, q->flags);
-+ type = FIELD_GET(MT_QFLAG_RRO_TYPE, q->flags);
-+ if (type == MT76_RRO_Q_DATA) {
-+ mt76_dma_queue_reset(dev, q, true);
-+ ret = mtk_wed_device_rro_rx_ring_setup(wed, ring, q->regs);
-+ } else if (type == MT76_RRO_Q_MSDU_PG) {
-+ mt76_dma_queue_reset(dev, q, true);
-+ ret = mtk_wed_device_msdu_pg_rx_ring_setup(wed, ring, q->regs);
-+ } else if (type == MT76_RRO_Q_IND) {
-+ mt76_dma_queue_reset(dev, q, false);
-+ mt76_dma_rx_fill(dev, q);
-+ ret = mtk_wed_device_ind_rx_ring_setup(wed, q->regs);
-+ }
-+ if (type != MT76_RRO_Q_IND) {
-+ q->head = q->ndesc - 1;
-+ q->queued = q->ndesc - 1;
-+ }
-+ } else {
-+ ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, 0);
-+ if (!ret)
-+ q->wed_regs = wed->rx_ring[ring].reg_base;
-+ }
- break;
- default:
- ret = -EINVAL;
-@@ -719,10 +811,25 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
- q->hw_idx = idx;
-
- size = q->ndesc * sizeof(struct mt76_desc);
-+ if (mt76_queue_is_rro_ind(q))
-+ size = q->ndesc * sizeof(struct mt76_rro_desc);
-+
- q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
- if (!q->desc)
- return -ENOMEM;
-
-+ if (mt76_queue_is_rro_ind(q)) {
-+ struct mt76_rro_ind *cmd;
-+ int i;
-+
-+ q->rro_desc = (struct mt76_rro_desc *)(q->desc);
-+ q->desc = NULL;
-+ for (i = 0; i < q->ndesc; i++) {
-+ cmd = (struct mt76_rro_ind *) &q->rro_desc[i];
-+ cmd->magic_cnt = MT_DMA_IND_CMD_MAGIC_CNT - 1;
-+ }
-+ }
-+
- size = q->ndesc * sizeof(*q->entry);
- q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
- if (!q->entry)
-@@ -732,8 +839,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
- if (ret)
- return ret;
-
-- if (!mt76_queue_is_txfree(q))
-- mt76_dma_queue_reset(dev, q);
-+ if (!mtk_wed_device_active(&dev->mmio.wed) ||
-+ (!mt76_queue_is_wed_txfree(q) &&
-+ !(mtk_wed_get_rx_capa(&dev->mmio.wed) &&
-+ q->flags & MT_QFLAG_RRO)))
-+ mt76_dma_queue_reset(dev, q, false);
-
- return 0;
- }
-@@ -768,8 +878,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
-
- spin_unlock_bh(&q->lock);
-
-- if (((q->flags & MT_QFLAG_WED) &&
-- FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) ||
-+ if (mt76_queue_is_wed_rx(q) ||
- (q->flags & MT_QFLAG_RRO))
- return;
-
-@@ -790,9 +899,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
- if (!q->ndesc)
- return;
-
-+ if (!q->desc)
-+ goto done;
-+
- for (i = 0; i < q->ndesc; i++)
- q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
-
-+done:
- mt76_dma_rx_cleanup(dev, q);
-
- /* reset WED rx queues */
-@@ -839,8 +952,8 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
- bool check_ddone = false;
- bool more;
-
-- if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
-- q->flags == MT_WED_Q_TXFREE) {
-+ 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;
- }
-@@ -1002,7 +1115,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
- mt76_for_each_q_rx(dev, i) {
- struct mt76_queue *q = &dev->q_rx[i];
-
-- if (mt76_queue_is_wed_rx(q))
-+ if (mtk_wed_device_active(&dev->mmio.wed) &&
-+ (q->flags & MT_QFLAG_RRO))
- continue;
-
- netif_napi_del(&dev->napi[i]);
-@@ -1014,6 +1128,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
-
- if (mtk_wed_device_active(&dev->mmio.wed_ext))
- mtk_wed_device_detach(&dev->mmio.wed_ext);
-+
- mt76_free_pending_txwi(dev);
- mt76_free_pending_rxwi(dev);
- }
-diff --git a/dma.h b/dma.h
-index 1b090d78..48037092 100644
---- a/dma.h
-+++ b/dma.h
-@@ -25,6 +25,13 @@
- #define MT_DMA_PPE_ENTRY GENMASK(30, 16)
- #define MT_DMA_INFO_PPE_VLD BIT(31)
-
-+#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
-+#define MT_DMA_CTL_VER_MASK BIT(7)
-+
-+#define MT_DMA_MAGIC_EN BIT(13)
-+
-+#define MT_DMA_IND_CMD_MAGIC_CNT 8
-+
- #define MT_DMA_HDR_LEN 4
- #define MT_RX_INFO_LEN 4
- #define MT_FCE_INFO_LEN 4
-@@ -37,6 +44,11 @@ struct mt76_desc {
- __le32 info;
- } __packed __aligned(4);
-
-+struct mt76_rro_desc {
-+ __le32 buf0;
-+ __le32 buf1;
-+} __packed __aligned(4);
-+
- enum mt76_qsel {
- MT_QSEL_MGMT,
- MT_QSEL_HCCA,
-diff --git a/mac80211.c b/mac80211.c
-index f7578308..3a5755f9 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -727,6 +727,7 @@ static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
- return;
- }
- }
-+
- __skb_queue_tail(&dev->rx_skb[q], skb);
- }
-
-diff --git a/mt76.h b/mt76.h
-index ee0dbdd7..e4351338 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -48,6 +48,18 @@
-
- #define MT76_TOKEN_FREE_THR 64
-
-+#define MT_QFLAG_RRO_RING GENMASK(6, 5)
-+#define MT_QFLAG_RRO_TYPE GENMASK(8, 7)
-+#define MT_QFLAG_RRO BIT(9)
-+#define MT_QFLAG_MAGIC BIT(10)
-+
-+#define __MT_RRO_Q(_type, _n) (MT_QFLAG_RRO | \
-+ FIELD_PREP(MT_QFLAG_RRO_TYPE, _type) | \
-+ FIELD_PREP(MT_QFLAG_RRO_RING, _n))
-+#define MT_RRO_Q_DATA(_n) __MT_RRO_Q(MT76_RRO_Q_DATA, _n)
-+#define MT_RRO_Q_MSDU_PG(_n) __MT_RRO_Q(MT76_RRO_Q_MSDU_PG, _n)
-+#define MT_RRO_Q_IND __MT_RRO_Q(MT76_RRO_Q_IND, 0)
-+
- #define MT_QFLAG_WED_RING GENMASK(1, 0)
- #define MT_QFLAG_WED_TYPE GENMASK(3, 2)
- #define MT_QFLAG_WED BIT(4)
-@@ -82,6 +94,12 @@ enum mt76_wed_type {
- MT76_WED_Q_RX,
- };
-
-+enum mt76_RRO_type {
-+ MT76_RRO_Q_DATA,
-+ MT76_RRO_Q_MSDU_PG,
-+ MT76_RRO_Q_IND,
-+};
-+
- struct mt76_bus_ops {
- u32 (*rr)(struct mt76_dev *dev, u32 offset);
- void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
-@@ -128,6 +146,16 @@ enum mt76_rxq_id {
- MT_RXQ_MAIN_WA,
- MT_RXQ_BAND2,
- MT_RXQ_BAND2_WA,
-+ MT_RXQ_RRO_BAND0,
-+ MT_RXQ_RRO_BAND1,
-+ MT_RXQ_RRO_BAND2,
-+ MT_RXQ_MSDU_PAGE_BAND0,
-+ MT_RXQ_MSDU_PAGE_BAND1,
-+ MT_RXQ_MSDU_PAGE_BAND2,
-+ MT_RXQ_TXFREE_BAND0,
-+ MT_RXQ_TXFREE_BAND1,
-+ MT_RXQ_TXFREE_BAND2,
-+ MT_RXQ_RRO_IND,
- __MT_RXQ_MAX
- };
-
-@@ -206,6 +234,7 @@ struct mt76_queue {
- spinlock_t lock;
- spinlock_t cleanup_lock;
- struct mt76_queue_entry *entry;
-+ struct mt76_rro_desc *rro_desc;
- struct mt76_desc *desc;
-
- u16 first;
-@@ -219,8 +248,8 @@ struct mt76_queue {
-
- u8 buf_offset;
- u8 hw_idx;
-- u8 flags;
--
-+ u8 magic_cnt;
-+ u32 flags;
- u32 wed_regs;
-
- dma_addr_t desc_dma;
-@@ -274,7 +303,7 @@ struct mt76_queue_ops {
-
- void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
-
-- void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
-+ void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q, bool skip);
- };
-
- enum mt76_phy_type {
-@@ -369,6 +398,17 @@ struct mt76_txq {
- bool aggr;
- };
-
-+struct mt76_rro_ind {
-+ u32 se_id : 12;
-+ u32 rsv : 4;
-+ u32 start_sn : 12;
-+ u32 ind_reason : 4;
-+ u32 ind_cnt : 13;
-+ u32 win_sz : 3;
-+ u32 rsv2 : 13;
-+ u32 magic_cnt : 3;
-+};
-+
- struct mt76_txwi_cache {
- struct list_head list;
- dma_addr_t dma_addr;
-@@ -1516,12 +1556,19 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
- return (q->flags & MT_QFLAG_WED) &&
- FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
- }
--static inline bool mt76_queue_is_txfree(struct mt76_queue *q)
-+
-+static inline bool mt76_queue_is_wed_txfree(struct mt76_queue *q)
- {
- return (q->flags & MT_QFLAG_WED) &&
- FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
- }
-
-+static inline bool mt76_queue_is_rro_ind(struct mt76_queue *q)
-+{
-+ return (q->flags & MT_QFLAG_RRO) &&
-+ FIELD_GET(MT_QFLAG_RRO_TYPE, q->flags) == MT76_RRO_Q_IND;
-+}
-+
- 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);
-@@ -1540,10 +1587,14 @@ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
- static inline int
- mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
- {
-- int token;
-+ int token, start = 0;
-+
-+ if (mtk_wed_device_active(&dev->mmio.wed))
-+ start = dev->mmio.wed.wlan.nbuf;
-
- spin_lock_bh(&dev->token_lock);
-- token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
-+ token = idr_alloc(&dev->token, *ptxwi, start, start + dev->token_size,
-+ GFP_ATOMIC);
- spin_unlock_bh(&dev->token_lock);
-
- return token;
-diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 428f3d08..45ccc7b5 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -64,6 +64,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
- RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
- RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
-
-+ if (dev->rro_support) {
-+ /* band0 */
-+ RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
-+ MT7996_RXQ_RRO_BAND0);
-+ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
-+ MT7996_RXQ_MSDU_PG_BAND0);
-+ RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
-+ MT7996_RXQ_TXFREE0);
-+ /* band1 */
-+ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
-+ MT7996_RXQ_MSDU_PG_BAND1);
-+ /* band2 */
-+ RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
-+ MT7996_RXQ_RRO_BAND2);
-+ RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
-+ MT7996_RXQ_MSDU_PG_BAND2);
-+ RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
-+ MT7996_RXQ_TXFREE2);
-+
-+ RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
-+ MT7996_RXQ_RRO_IND);
-+ }
-+
- /* data tx queue */
- TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
- TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
-@@ -102,6 +125,22 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
- mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x2));
- mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
- mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x10));
-+ if (dev->rro_support) {
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
-+ PREFETCH(0x10));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
-+ PREFETCH(0x10));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
-+ PREFETCH(0x4));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
-+ PREFETCH(0x4));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
-+ PREFETCH(0x4));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
-+ PREFETCH(0x4));
-+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
-+ PREFETCH(0x4));
-+ }
- #undef PREFETCH
-
- mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
-@@ -161,6 +200,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
-
- void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
- {
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
- u32 hif1_ofs = 0;
- u32 irq_mask;
-
-@@ -169,11 +209,16 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
-
- /* enable wpdma tx/rx */
- if (!reset) {
-- mt76_set(dev, MT_WFDMA0_GLO_CFG,
-- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
-+ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
-+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
-+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO);
-+ else
-+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
-+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_RX_DMA_EN |
-+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
-+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
-
- if (dev->hif2)
- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
-@@ -185,8 +230,8 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
-
- /* enable interrupts for TX/RX rings */
- irq_mask = MT_INT_MCU_CMD |
-- MT_INT_RX_DONE_MCU |
-- MT_INT_TX_DONE_MCU;
-+ MT_INT_RX_DONE_MCU |
-+ MT_INT_TX_DONE_MCU;
-
- if (mt7996_band_valid(dev, MT_BAND0))
- irq_mask |= MT_INT_BAND0_RX_DONE;
-@@ -197,14 +242,14 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
- if (mt7996_band_valid(dev, MT_BAND2))
- irq_mask |= MT_INT_BAND2_RX_DONE;
-
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) {
-+ if (mtk_wed_device_active(wed) && wed_reset) {
- u32 wed_irq_mask = irq_mask;
-
- wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
-
- mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
-
-- mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
-+ mtk_wed_device_start(wed, wed_irq_mask);
- }
-
- irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
-@@ -298,7 +343,8 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- /* fix hardware limitation, pcie1's rx ring3 is not available
- * so, redirect pcie0 rx ring3 interrupt to pcie1
- */
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->rro_support)
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ dev->rro_support)
- mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
- MT_WFDMA0_RX_INT_SEL_RING6);
- else
-@@ -311,6 +357,78 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
- return 0;
- }
-
-+int mt7996_dma_rro_init(struct mt7996_dev *dev)
-+{
-+ int ret;
-+ u32 hif1_ofs = 0;
-+ u32 wed_irq_mask;
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+
-+ if (dev->hif2)
-+ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-+
-+ /* ind cmd */
-+ dev->mt76.q_rx[MT_RXQ_RRO_IND].flags = MT_RRO_Q_IND | MT_WED_Q_RX(0);
-+ dev->mt76.q_rx[MT_RXQ_RRO_IND].flags |= MT_WED_Q_RX(0);
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_IND],
-+ MT_RXQ_ID(MT_RXQ_RRO_IND),
-+ MT7996_RX_RING_SIZE,
-+ 0, MT_RXQ_RRO_IND_RING_BASE);
-+ if (ret)
-+ return ret;
-+
-+ /* rx msdu page queue for band0 */
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags = MT_RRO_Q_MSDU_PG(0);
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags |= MT_QFLAG_MAGIC;
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags |= MT_WED_Q_RX(0);
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0],
-+ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
-+ MT7996_RX_RING_SIZE,
-+ MT7996_RX_MSDU_PAGE_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
-+ if (ret)
-+ return ret;
-+
-+ if (mt7996_band_valid(dev, MT_BAND1)) {
-+ /* rx msdu page queue for band1 */
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags = MT_RRO_Q_MSDU_PG(1);
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags |= MT_QFLAG_MAGIC;
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags |= MT_WED_Q_RX(1);
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1],
-+ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
-+ MT7996_RX_RING_SIZE,
-+ MT7996_RX_MSDU_PAGE_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (mt7996_band_valid(dev, MT_BAND2)) {
-+ /* rx msdu page queue for band2 */
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags = MT_RRO_Q_MSDU_PG(2);
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags |= MT_QFLAG_MAGIC;
-+ dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags |= MT_WED_Q_RX(0);
-+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2],
-+ MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
-+ MT7996_RX_RING_SIZE,
-+ MT7996_RX_MSDU_PAGE_SIZE,
-+ MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
-+ if (ret)
-+ return ret;
-+ }
-+
-+ wed_irq_mask = dev->mt76.mmio.irqmask |
-+ MT_INT_RRO_RX_DONE |
-+ MT_INT_TX_DONE_BAND2;
-+
-+ mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
-+
-+ mtk_wed_device_start_hwrro(wed, wed_irq_mask, false);
-+ mt7996_irq_enable(dev, wed_irq_mask);
-+
-+ return 0;
-+}
-+
- int mt7996_dma_init(struct mt7996_dev *dev)
- {
- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-@@ -380,6 +498,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- return ret;
-
- /* rx data queue for band0 and band1 */
-+ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
-+ dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0);
-+
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
- MT_RXQ_ID(MT_RXQ_MAIN),
- MT7996_RX_RING_SIZE,
-@@ -403,9 +524,6 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- if (mt7996_band_valid(dev, MT_BAND2)) {
- /* rx data queue for band2 */
- rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
-- if (mtk_wed_device_active(wed))
-- rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
--
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
- MT_RXQ_ID(MT_RXQ_BAND2),
- MT7996_RX_RING_SIZE,
-@@ -429,11 +547,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- return ret;
- }
-
--
-- if (dev->rro_support) {
-+ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
-+ dev->rro_support) {
- /* rx rro data queue for band0 */
- dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags = MT_RRO_Q_DATA(0);
- dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_QFLAG_MAGIC;
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_WED_Q_RX(0);
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
- MT_RXQ_ID(MT_RXQ_RRO_BAND0),
- MT7996_RX_RING_SIZE,
-@@ -443,8 +562,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- return ret;
-
- /* tx free notify event from WA for band0 */
-- if (mtk_wed_device_active(wed))
-- dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
-+ dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
- MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
- MT7996_RX_MCU_RING_SIZE,
-@@ -457,6 +575,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- /* rx rro data queue for band2 */
- dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags = MT_RRO_Q_DATA(1);
- dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_QFLAG_MAGIC;
-+ dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_WED_Q_RX(1);
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
- MT_RXQ_ID(MT_RXQ_RRO_BAND2),
- MT7996_RX_RING_SIZE,
-@@ -534,18 +653,18 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
-
- /* reset hw queues */
- for (i = 0; i < __MT_TXQ_MAX; i++) {
-- mt76_queue_reset(dev, dev->mphy.q_tx[i]);
-+ mt76_queue_reset(dev, dev->mphy.q_tx[i], false);
- if (phy2)
-- mt76_queue_reset(dev, phy2->q_tx[i]);
-+ mt76_queue_reset(dev, phy2->q_tx[i], false);
- if (phy3)
-- mt76_queue_reset(dev, phy3->q_tx[i]);
-+ mt76_queue_reset(dev, phy3->q_tx[i], false);
- }
-
- for (i = 0; i < __MT_MCUQ_MAX; i++)
-- mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
-+ mt76_queue_reset(dev, dev->mt76.q_mcu[i], false);
-
- mt76_for_each_q_rx(&dev->mt76, i) {
-- mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
-+ mt76_queue_reset(dev, &dev->mt76.q_rx[i], false);
- }
-
- mt76_tx_status_check(&dev->mt76, true);
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 6cfbc50d..d70dcf9f 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -496,8 +496,13 @@ void mt7996_mac_init(struct mt7996_dev *dev)
-
- /* rro module init */
- mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
-- mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
-- mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
-+ if (dev->rro_support) {
-+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
-+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
-+ } else {
-+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
-+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
-+ }
-
- mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
- MCU_WA_PARAM_HW_PATH_HIF_VER,
-@@ -650,6 +655,114 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
- msleep(20);
- }
-
-+static int mt7996_rro_init(struct mt7996_dev *dev)
-+{
-+ struct mt7996_rro_addr *ptr;
-+ struct mt7996_rro_cfg *rro = &dev->rro;
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+ u32 size, val = 0, reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
-+ int i, j;
-+ void *buf;
-+
-+ for (i = 0; i < MT7996_RRO_BA_BITMAP_CR_CNT; i++) {
-+ buf = dmam_alloc_coherent(dev->mt76.dma_dev,
-+ MT7996_BA_BITMAP_SZ_PER_CR,
-+ &rro->ba_bitmap_cache_pa[i],
-+ GFP_KERNEL);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ rro->ba_bitmap_cache_va[i] = buf;
-+ }
-+
-+ rro->win_sz = MT7996_RRO_WIN_SIZE_MAX;
-+ for (i = 0; i < MT7996_RRO_ADDR_ELEM_CR_CNT; i++) {
-+ size = MT7996_RRO_SESSION_PER_CR *
-+ rro->win_sz * sizeof(struct mt7996_rro_addr);
-+
-+ buf = dmam_alloc_coherent(dev->mt76.dma_dev, size,
-+ &rro->addr_elem_alloc_pa[i],
-+ GFP_KERNEL);
-+ if (!buf)
-+ return -ENOMEM;
-+ rro->addr_elem_alloc_va[i] = buf;
-+
-+ memset(rro->addr_elem_alloc_va[i], 0, size);
-+
-+ ptr = rro->addr_elem_alloc_va[i];
-+ for (j = 0; j < MT7996_RRO_SESSION_PER_CR * rro->win_sz; j++, ptr++)
-+ ptr->signature = 0xff;
-+
-+ wed->wlan.ind_cmd.addr_elem_phys[i] = rro->addr_elem_alloc_pa[i];
-+ }
-+
-+ rro->particular_se_id = MT7996_RRO_SESSION_MAX;
-+ size = rro->win_sz * sizeof(struct mt7996_rro_addr);
-+ buf = dmam_alloc_coherent(dev->mt76.dma_dev, size,
-+ &rro->particular_session_pa,
-+ GFP_KERNEL);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ rro->particular_session_va = buf;
-+ ptr = rro->particular_session_va;
-+ for (j = 0; j < rro->win_sz; j++, ptr++)
-+ ptr->signature = 0xff;
-+
-+ INIT_LIST_HEAD(&rro->pg_addr_cache);
-+ for (i = 0; i < MT7996_RRO_MSDU_PG_HASH_SIZE; i++)
-+ INIT_LIST_HEAD(&rro->pg_hash_head[i]);
-+
-+ /* rro hw init */
-+ /* TODO: remove line after WM has set */
-+ mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
-+
-+ /* setup BA bitmap cache address */
-+ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
-+ rro->ba_bitmap_cache_pa[0]);
-+ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
-+ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
-+ rro->ba_bitmap_cache_pa[1]);
-+ mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
-+
-+ /* setup Address element address */
-+ for (i = 0; i < MT7996_RRO_ADDR_ELEM_CR_CNT; i++) {
-+ mt76_wr(dev, reg, rro->addr_elem_alloc_pa[i] >> 4);
-+ reg += 4;
-+ }
-+
-+ /* setup Address element address - separate address segment mode */
-+ mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
-+ MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
-+
-+ wed->wlan.ind_cmd.win_size = ffs(rro->win_sz) - 6;
-+ wed->wlan.ind_cmd.particular_sid = rro->particular_se_id;
-+ wed->wlan.ind_cmd.particular_se_phys = rro->particular_session_pa;
-+ wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_CR_CNT;
-+ wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
-+
-+ mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
-+ mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
-+ MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
-+
-+ /* particular session configure */
-+ /* use max session idx + 1 as particular session id */
-+ mt76_wr(dev, MT_RRO_PARTICULAR_CFG0,
-+ rro->particular_session_pa);
-+
-+ val = FIELD_PREP(MT_RRO_PARTICULAR_SID,
-+ MT7996_RRO_SESSION_MAX);
-+ val |= MT_RRO_PARTICULAR_CONFG_EN;
-+ mt76_wr(dev, MT_RRO_PARTICULAR_CFG1, val);
-+
-+ /* interrupt enable */
-+ mt76_wr(dev, MT_RRO_HOST_INT_ENA,
-+ MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
-+
-+ /* rro ind cmd queue init */
-+ return mt7996_dma_rro_init(dev);
-+}
-+
- static int mt7996_init_hardware(struct mt7996_dev *dev)
- {
- int ret, idx;
-@@ -677,6 +790,13 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
- if (ret)
- return ret;
-
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ dev->rro_support) {
-+ ret = mt7996_rro_init(dev);
-+ if (ret)
-+ return ret;
-+ }
-+
- ret = mt7996_eeprom_init(dev);
- if (ret < 0)
- return ret;
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index fc2d9269..4fbbc077 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -614,8 +614,37 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
- return 0;
- }
-
-+static void
-+mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
-+ struct mt7996_sta *msta, struct sk_buff *skb,
-+ u32 info)
-+{
-+ struct ieee80211_vif *vif;
-+ struct wireless_dev *wdev;
-+
-+ if (!msta || !msta->vif)
-+ return;
-+
-+ if (!mt76_queue_is_wed_rx(q))
-+ return;
-+
-+ if (!(info & MT_DMA_INFO_PPE_VLD))
-+ return;
-+
-+ vif = container_of((void *)msta->vif, struct ieee80211_vif,
-+ drv_priv);
-+ wdev = ieee80211_vif_to_wdev(vif);
-+ skb->dev = wdev->netdev;
-+
-+ mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
-+ FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
-+ FIELD_GET(MT_DMA_PPE_ENTRY, info));
-+}
-+
-+
- static int
--mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
-+mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
-+ struct sk_buff *skb, u32 *info)
- {
- struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
- struct mt76_phy *mphy = &dev->mt76.phy;
-@@ -640,7 +669,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
- u16 seq_ctrl = 0;
- __le16 fc = 0;
- int idx;
-+ u8 hw_aggr = false;
-+ struct mt7996_sta *msta = NULL;
-
-+ hw_aggr = status->aggr;
- memset(status, 0, sizeof(*status));
-
- band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
-@@ -667,8 +699,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
- status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
-
- if (status->wcid) {
-- struct mt7996_sta *msta;
--
- msta = container_of(status->wcid, struct mt7996_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
- if (list_empty(&msta->poll_list))
-@@ -871,12 +901,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
- #endif
- } else {
- status->flag |= RX_FLAG_8023;
-+ mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
-+ *info);
- }
-
- if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
- mt7996_mac_decode_he_radiotap(skb, rxv, mode);
-
-- if (!status->wcid || !ieee80211_is_data_qos(fc))
-+ if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
- return 0;
-
- status->aggr = unicast &&
-@@ -1604,7 +1636,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- dev_kfree_skb(skb);
- break;
- case PKT_TYPE_NORMAL:
-- if (!mt7996_mac_fill_rx(dev, skb)) {
-+ if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
- mt76_rx(&dev->mt76, q, skb);
- return;
- }
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 59f22f6d..1891c0d7 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -949,7 +949,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
- static int
- mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
- struct ieee80211_ampdu_params *params,
-- bool enable, bool tx)
-+ bool enable, bool tx, bool rro_enable)
- {
- struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
- struct sta_rec_ba_uni *ba;
-@@ -970,6 +970,8 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
- ba->ba_en = enable << params->tid;
- ba->amsdu = params->amsdu;
- ba->tid = params->tid;
-+ if (rro_enable && !tx && enable)
-+ ba->ba_rdd_rro = true;
-
- return mt76_mcu_skb_send_msg(dev, skb,
- MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
-@@ -987,7 +989,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
- msta->wcid.amsdu = false;
-
- return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
-- enable, true);
-+ enable, true, dev->rro_support);
- }
-
- int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
-@@ -998,7 +1000,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
- struct mt7996_vif *mvif = msta->vif;
-
- return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
-- enable, false);
-+ enable, false, dev->rro_support);
- }
-
- static void
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index b9e47e73..9960dca7 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -346,9 +346,15 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
- }
-
-+ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
-+ wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
-+ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
-+ MT7996_RXQ_BAND0 * MT_RING_SIZE;
-+
- wed->wlan.chip_id = 0x7991;
- wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
- } else {
-+ wed->wlan.hwrro = dev->rro_support; /* default on */
- wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
- wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
- wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
-@@ -360,13 +366,33 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
- MT7996_RXQ_BAND0 * MT_RING_SIZE;
-
-+ wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
-+ MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
-+ MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
-+ wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
-+ MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
-+ MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
-+ wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
-+ MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
-+ MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
-+
- wed->wlan.rx_nbuf = 65536;
- wed->wlan.rx_npkt = 24576;
-+ if (dev->hif2)
-+ wed->wlan.rx_npkt += 8192;
-+
- wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
-
- wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
- wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
-
-+ wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
-+ wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
-+
-+ wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
-+ wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
-+ wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
-+
- wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
- wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
- if (dev->rro_support) {
-@@ -378,6 +404,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
- MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
- }
-+
-+ dev->mt76.rx_token_size += wed->wlan.rx_npkt;
- }
-
- wed->wlan.nbuf = 16384;
-@@ -394,8 +422,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
- wed->wlan.update_wo_rx_stats = NULL;
-
-- dev->mt76.rx_token_size += wed->wlan.rx_npkt;
--
- if (mtk_wed_device_attach(wed))
- return 0;
-
-@@ -557,10 +583,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
- irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
- {
- struct mt7996_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);
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
-+ mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
- else
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-
-@@ -592,6 +617,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
- SURVEY_INFO_TIME_RX |
- SURVEY_INFO_TIME_BSS_RX,
- .token_size = MT7996_TOKEN_SIZE,
-+ .rx_token_size = MT7996_RX_TOKEN_SIZE,
- .tx_prepare_skb = mt7996_tx_prepare_skb,
- .tx_complete_skb = mt76_connac_tx_complete_skb,
- .rx_skb = mt7996_queue_rx_skb,
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 43f20da4..836c7db7 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -39,6 +39,7 @@
- #define MT7996_EEPROM_SIZE 7680
- #define MT7996_EEPROM_BLOCK_SIZE 16
- #define MT7996_TOKEN_SIZE 16384
-+#define MT7996_RX_TOKEN_SIZE 16384
-
- #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
- #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
-@@ -63,6 +64,24 @@
- #define MT7996_SKU_RATE_NUM 417
- #define MT7996_SKU_PATH_NUM 494
-
-+#define MT7996_RRO_MSDU_PG_HASH_SIZE 127
-+#define MT7996_RRO_SESSION_MAX 1024
-+#define MT7996_RRO_WIN_SIZE_MAX 1024
-+#define MT7996_RRO_ADDR_ELEM_CR_CNT 128
-+#define MT7996_RRO_BA_BITMAP_CR_CNT 2
-+#define MT7996_RRO_SESSION_PER_CR (MT7996_RRO_SESSION_MAX / \
-+ MT7996_RRO_ADDR_ELEM_CR_CNT)
-+#define MT7996_BA_BITMAP_SZ_PER_SESSION 128
-+#define MT7996_BA_BITMAP_SZ_PER_CR ((MT7996_RRO_SESSION_MAX * \
-+ MT7996_BA_BITMAP_SZ_PER_SESSION) / \
-+ MT7996_RRO_BA_BITMAP_CR_CNT)
-+#define MT7996_SKB_TRUESIZE(x) ((x) + \
-+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
-+#define MT7996_RX_BUF_SIZE MT7996_SKB_TRUESIZE(1800)
-+#define MT7996_RX_MSDU_PAGE_SIZE MT7996_SKB_TRUESIZE(128)
-+
-+#define MT7996_WED_RX_TOKEN_SIZE 32768
-+
- struct mt7996_vif;
- struct mt7996_sta;
- struct mt7996_dfs_pulse;
-@@ -102,6 +121,16 @@ enum mt7996_rxq_id {
- MT7996_RXQ_BAND0 = 4,
- MT7996_RXQ_BAND1 = 4,/* unused */
- MT7996_RXQ_BAND2 = 5,
-+ MT7996_RXQ_RRO_BAND0 = 8,
-+ MT7996_RXQ_RRO_BAND1 = 8,/* unused */
-+ MT7996_RXQ_RRO_BAND2 = 6,
-+ MT7996_RXQ_MSDU_PG_BAND0 = 10,
-+ MT7996_RXQ_MSDU_PG_BAND1 = 11,
-+ MT7996_RXQ_MSDU_PG_BAND2 = 12,
-+ MT7996_RXQ_TXFREE0 = 9,
-+ MT7996_RXQ_TXFREE1 = 9,
-+ MT7996_RXQ_TXFREE2 = 7,
-+ MT7996_RXQ_RRO_IND = 0,
- };
-
- struct mt7996_twt_flow {
-@@ -272,6 +301,31 @@ struct mt7996_air_monitor_ctrl {
- };
- #endif
-
-+struct mt7996_rro_addr {
-+ u32 head_pkt_l;
-+ u32 head_pkt_h : 4;
-+ u32 seg_cnt : 11;
-+ u32 out_of_range: 1;
-+ u32 rsv : 8;
-+ u32 signature : 8;
-+};
-+
-+struct mt7996_rro_cfg {
-+ u32 ind_signature;
-+ void *ba_bitmap_cache_va[MT7996_RRO_BA_BITMAP_CR_CNT];
-+ void *addr_elem_alloc_va[MT7996_RRO_ADDR_ELEM_CR_CNT];
-+ void *particular_session_va;
-+ u32 particular_se_id;
-+ dma_addr_t ba_bitmap_cache_pa[MT7996_RRO_BA_BITMAP_CR_CNT];
-+ dma_addr_t addr_elem_alloc_pa[MT7996_RRO_ADDR_ELEM_CR_CNT];
-+ dma_addr_t particular_session_pa;
-+ u16 win_sz;
-+
-+ spinlock_t lock;
-+ struct list_head pg_addr_cache;
-+ struct list_head pg_hash_head[MT7996_RRO_MSDU_PG_HASH_SIZE];
-+};
-+
- struct mt7996_phy {
- struct mt76_phy *mt76;
- struct mt7996_dev *dev;
-@@ -390,6 +444,9 @@ struct mt7996_dev {
- bool flash_mode:1;
- bool has_eht:1;
-
-+ bool rro_support:1;
-+ struct mt7996_rro_cfg rro;
-+
- bool testmode_enable;
- bool bin_file_mode;
- u8 eeprom_mode;
-@@ -709,6 +766,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- struct ieee80211_sta *sta,
- struct mt76_tx_info *tx_info);
- void mt7996_tx_token_put(struct mt7996_dev *dev);
-+int mt7996_dma_rro_init(struct mt7996_dev *dev);
- void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb, u32 *info);
- bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
-diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 5ed7bcca..47fa965f 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -39,6 +39,40 @@ enum base_rev {
-
- #define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
-
-+
-+/* RRO TOP */
-+#define MT_RRO_TOP_BASE 0xA000
-+#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
-+
-+#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8)
-+#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
-+#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
-+#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
-+#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
-+#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
-+
-+#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38)
-+#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C)
-+#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40)
-+#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31)
-+
-+#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C)
-+#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60)
-+#define MT_RRO_PARTICULAR_CONFG_EN BIT(31)
-+#define MT_RRO_PARTICULAR_SID GENMASK(30, 16)
-+
-+#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70)
-+#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74)
-+#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204)
-+#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0)
-+
-+#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
-+
-+#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
-+#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
-+#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
-+
-+
- #define MT_MCU_INT_EVENT 0x2108
- #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
- #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
-@@ -400,6 +434,7 @@ enum base_rev {
- #define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300)
- #define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300)
- #define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
-+#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
-
- #define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
- MT_MCUQ_ID(q) * 0x4)
-@@ -427,6 +462,15 @@ enum base_rev {
- #define MT_INT_MCU_CMD BIT(29)
- #define MT_INT_RX_TXFREE_EXT BIT(26)
-
-+#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
-+#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
-+#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
-+#define MT_INT_RX_DONE_RRO_IND BIT(11)
-+#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
-+#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
-+#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
-+
-+
- #define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
- #define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
-
-@@ -434,20 +478,31 @@ enum base_rev {
- MT_INT_RX(MT_RXQ_MCU_WA))
-
- #define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
-- MT_INT_RX(MT_RXQ_MAIN_WA))
-+ MT_INT_RX(MT_RXQ_MAIN_WA) | \
-+ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
-
- #define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
- MT_INT_RX(MT_RXQ_BAND1_WA) | \
-- MT_INT_RX(MT_RXQ_MAIN_WA))
-+ MT_INT_RX(MT_RXQ_MAIN_WA) | \
-+ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
-
- #define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \
- MT_INT_RX(MT_RXQ_BAND2_WA) | \
-- MT_INT_RX(MT_RXQ_MAIN_WA))
-+ MT_INT_RX(MT_RXQ_MAIN_WA) | \
-+ MT_INT_RX(MT_RXQ_TXFREE_BAND0))
-+
-+#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
-+ MT_INT_RX(MT_RXQ_RRO_BAND1) | \
-+ MT_INT_RX(MT_RXQ_RRO_BAND2) | \
-+ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
-+ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
-+ MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
-
- #define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
- MT_INT_BAND0_RX_DONE | \
- MT_INT_BAND1_RX_DONE | \
-- MT_INT_BAND2_RX_DONE)
-+ MT_INT_BAND2_RX_DONE | \
-+ MT_INT_RRO_RX_DONE)
-
- #define MT_INT_TX_DONE_FWDL BIT(26)
- #define MT_INT_TX_DONE_MCU_WM BIT(27)
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch
deleted file mode 100644
index 7fdee4c..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From e5136e5f940adf55f1e7604960dba89e24a187bb Mon Sep 17 00:00:00 2001
-From: "sujuan.chen" <sujuan.chen@mediatek.com>
-Date: Thu, 13 Apr 2023 14:12:16 +0800
-Subject: [PATCH 2005/2008] wifi: mt76: mt7996: wed: add mt7996_net_setup_tc to
- support wifi2wifi offload
-
-Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
----
- mt7996/main.c | 19 +++++++++++++++++++
- 1 file changed, 19 insertions(+)
-
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 50fa6523..cebac4ab 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -1446,6 +1446,24 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
- return 0;
- }
-
-+static int mt7996_net_setup_tc(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct net_device *ndev,
-+ enum tc_setup_type type,
-+ void *type_data)
-+
-+{
-+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
-+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+
-+ if (!mtk_wed_device_active(wed))
-+ return -ENODEV;
-+
-+ mtk_wed_device_setup_tc(wed, ndev, type, type_data);
-+
-+ return 0;
-+}
-+
- #endif
-
- const struct ieee80211_ops mt7996_ops = {
-@@ -1496,5 +1514,6 @@ const struct ieee80211_ops mt7996_ops = {
- .set_radar_background = mt7996_set_radar_background,
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- .net_fill_forward_path = mt7996_net_fill_forward_path,
-+ .net_setup_tc = mt7996_net_setup_tc,
- #endif
- };
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch
new file mode 100644
index 0000000..306c6e6
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch
@@ -0,0 +1,93 @@
+From 161fde22deceee4e676f62b9d3b0366ffe52dc07 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Fri, 6 Oct 2023 14:01:41 +0800
+Subject: [PATCH 69/98] wifi: mt76 : wed : change pcie0 R5 to pcie1 to get 6G
+ ICS
+
+---
+ mt7996/dma.c | 4 ++++
+ mt7996/init.c | 6 ++----
+ mt7996/mmio.c | 5 ++++-
+ mt7996/regs.h | 6 ++++++
+ 4 files changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 23f6f16..2397fe5 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -519,6 +519,10 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (mt7996_band_valid(dev, MT_BAND2)) {
+ /* rx data queue for band2 */
+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
++ if (mtk_wed_device_active(wed_hif2) && mtk_wed_get_rx_capa(wed_hif2)) {
++ dev->mt76.q_rx[MT_RXQ_BAND2].flags = MT_WED_Q_RX(0);
++ dev->mt76.q_rx[MT_RXQ_BAND2].wed = wed_hif2;
++ }
+ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ MT_RXQ_ID(MT_RXQ_BAND2),
+ MT7996_RX_RING_SIZE,
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 1f01f24..5627605 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -619,10 +619,8 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ goto error;
+
+ if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
+- u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
+-
+- mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
+- mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask);
++ mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TRX_DONE_EXT);
++ mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, MT_INT_TRX_DONE_EXT);
+ }
+
+ return 0;
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 2132b2e..2e395d1 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -504,12 +504,15 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ dev->mt76.mmio.irqmask);
+ if (intr1 & MT_INT_RX_TXFREE_EXT)
+ napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
++
++ if (intr1 & MT_INT_RX_DONE_BAND2_EXT)
++ napi_schedule(&dev->mt76.napi[MT_RXQ_BAND2]);
+ }
+
+ 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);
+- intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
++ intr |= (intr1 & ~MT_INT_TRX_DONE_EXT);
+ } else {
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ if (dev->hif2)
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 38467d9..a0b5270 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -501,6 +501,8 @@ enum offs_rev {
+ #define MT_INT_RX_TXFREE_MAIN BIT(17)
+ #define MT_INT_RX_TXFREE_TRI BIT(15)
+ #define MT_INT_MCU_CMD BIT(29)
++
++#define MT_INT_RX_DONE_BAND2_EXT BIT(23)
+ #define MT_INT_RX_TXFREE_EXT BIT(26)
+
+ #define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
+@@ -551,6 +553,10 @@ enum offs_rev {
+ #define MT_INT_TX_DONE_BAND1 BIT(31)
+ #define MT_INT_TX_DONE_BAND2 BIT(15)
+
++#define MT_INT_TRX_DONE_EXT (MT_INT_TX_DONE_BAND2 | \
++ MT_INT_RX_DONE_BAND2_EXT | \
++ MT_INT_RX_TXFREE_EXT)
++
+ #define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \
+ MT_INT_TX_MCU(MT_MCUQ_WM) | \
+ MT_INT_TX_MCU(MT_MCUQ_FWDL))
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch
new file mode 100644
index 0000000..7511279
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch
@@ -0,0 +1,65 @@
+From a2bd3309c6c1ea4d63d8ac3fc066914186740ab5 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Fri, 6 Oct 2023 15:48:37 +0800
+Subject: [PATCH 70/98] wifi: mt76: mt7996: add rro elem free when rmmod wifi
+ module
+
+---
+ mt7996/init.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 5627605..1ece390 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -670,6 +670,38 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
+ msleep(20);
+ }
+
++static int mt7996_rro_free(struct mt7996_dev *dev)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
++ if (dev->wed_rro.ba_bitmap[i].ptr)
++ dmam_free_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_BA_BITMAP_CR_SIZE,
++ dev->wed_rro.ba_bitmap[i].ptr,
++ dev->wed_rro.ba_bitmap[i].phy_addr);
++ }
++
++ for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
++ if (dev->wed_rro.addr_elem[i].ptr) {
++ dmam_free_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_WINDOW_MAX_SIZE *
++ sizeof(struct mt7996_wed_rro_addr),
++ dev->wed_rro.addr_elem[i].ptr,
++ dev->wed_rro.addr_elem[i].phy_addr);
++ }
++ }
++
++ if (dev->wed_rro.session.ptr)
++ dmam_free_coherent(dev->mt76.dma_dev,
++ MT7996_RRO_WINDOW_MAX_LEN *
++ sizeof(struct mt7996_wed_rro_addr),
++ dev->wed_rro.session.ptr,
++ dev->wed_rro.session.phy_addr);
++
++ return 0;
++}
++
+ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
+ {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+@@ -1295,6 +1327,8 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
+ mt7996_coredump_unregister(dev);
+ mt76_unregister_device(&dev->mt76);
+ mt7996_mcu_exit(dev);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->has_rro)
++ mt7996_rro_free(dev);
+ mt7996_tx_token_put(dev);
+ mt7996_dma_cleanup(dev);
+ tasklet_disable(&dev->mt76.irq_tasklet);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-add-SER-support-for-wed3.0.patch
similarity index 61%
rename from recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-add-SER-support-for-wed3.0.patch
index 3d25c27..2ba1f4e 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-add-SER-support-for-wed3.0.patch
@@ -1,60 +1,36 @@
-From 5df084a32eac68dd66a3b833cf5f718118850b08 Mon Sep 17 00:00:00 2001
+From 487a6e92fb6ce81d043b5a7632133379b8bcfbcb Mon Sep 17 00:00:00 2001
From: mtk27745 <rex.lu@mediatek.com>
Date: Tue, 23 May 2023 12:06:29 +0800
-Subject: [PATCH 2008/2008] wifi: mt76: add SER support for wed3.0
+Subject: [PATCH 71/98] wifi: mt76: add SER support for wed3.0
Change-Id: I2711b9dc336fca9a1ae32a8fbf27810a7e27b1e3
---
- dma.c | 7 +++++--
- mt7996/dma.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
- mt7996/mac.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
- mt7996/mmio.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 145 insertions(+), 6 deletions(-)
+ dma.c | 4 +++-
+ mt7996/dma.c | 42 +++++++++++++++++++++++++++++++++++++++---
+ mt7996/mac.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
+ mt7996/mmio.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 136 insertions(+), 5 deletions(-)
diff --git a/dma.c b/dma.c
-index e5b4d898..e31f6390 100644
+index f48ec57..141a97b 100644
--- a/dma.c
+++ b/dma.c
-@@ -778,8 +778,9 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
- q->head = q->ndesc - 1;
- q->queued = q->ndesc - 1;
- }
-+ q->flags = flags;
- } else {
-- ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, 0);
-+ ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
- if (!ret)
- q->wed_regs = wed->rx_ring[ring].reg_base;
- }
-@@ -910,7 +911,9 @@ done:
+@@ -898,7 +898,9 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
/* reset WED rx queues */
mt76_dma_wed_setup(dev, q, true);
-- if (q->flags != MT_WED_Q_TXFREE) {
-+ if (q->flags != MT_WED_Q_TXFREE &&
-+ !((q->flags & MT_QFLAG_RRO) &&
+- if (!mt76_queue_is_wed_tx_free(q)) {
++ if (!mt76_queue_is_wed_tx_free(q) &&
++ !(mt76_queue_is_wed_rro(q) &&
+ mtk_wed_device_active(&dev->mmio.wed))) {
mt76_dma_sync_idx(dev, q);
mt76_dma_rx_fill(dev, q);
}
diff --git a/mt7996/dma.c b/mt7996/dma.c
-index c5c7f160..471ae81c 100644
+index 2397fe5..b2c7ae6 100644
--- a/mt7996/dma.c
+++ b/mt7996/dma.c
-@@ -524,6 +524,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- if (mt7996_band_valid(dev, MT_BAND2)) {
- /* rx data queue for band2 */
- rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
-+ if (mtk_wed_device_active(wed)) {
-+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
-+ if (mtk_wed_get_rx_capa(wed))
-+ dev->mt76.q_rx[MT_RXQ_BAND2].flags = MT_WED_Q_RX(1);
-+ }
-+
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
- MT_RXQ_ID(MT_RXQ_BAND2),
- MT7996_RX_RING_SIZE,
-@@ -611,11 +617,35 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+@@ -615,11 +615,35 @@ int mt7996_dma_init(struct mt7996_dev *dev)
return 0;
}
@@ -75,7 +51,7 @@
+static void
+mt7996_dma_reset_tx_queue(struct mt7996_dev *dev, struct mt76_queue *q)
+{
-+ mt76_queue_reset(dev, q, false);
++ mt76_queue_reset(dev, q);
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ mt76_dma_wed_setup(&dev->mt76, q, true);
+}
@@ -86,16 +62,16 @@
struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-+ struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
++ struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
int i;
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
-@@ -649,21 +679,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+@@ -653,21 +677,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
if (force)
mt7996_wfsys_reset(dev);
-+ if (dev->hif2 && mtk_wed_device_active(wed_ext))
-+ mtk_wed_device_dma_reset(wed_ext);
++ if (dev->hif2 && mtk_wed_device_active(wed_hif2))
++ mtk_wed_device_dma_reset(wed_hif2);
+
+ if (mtk_wed_device_active(wed))
+ mtk_wed_device_dma_reset(wed);
@@ -105,61 +81,61 @@
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++) {
-- mt76_queue_reset(dev, dev->mphy.q_tx[i], false);
+- mt76_queue_reset(dev, dev->mphy.q_tx[i]);
+ mt7996_dma_reset_tx_queue(dev, dev->mphy.q_tx[i]);
if (phy2)
-- mt76_queue_reset(dev, phy2->q_tx[i], false);
+- mt76_queue_reset(dev, phy2->q_tx[i]);
+ mt7996_dma_reset_tx_queue(dev, phy2->q_tx[i]);
if (phy3)
-- mt76_queue_reset(dev, phy3->q_tx[i], false);
+- mt76_queue_reset(dev, phy3->q_tx[i]);
+ mt7996_dma_reset_tx_queue(dev, phy3->q_tx[i]);
}
for (i = 0; i < __MT_MCUQ_MAX; i++)
- mt76_queue_reset(dev, dev->mt76.q_mcu[i], false);
+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
mt76_for_each_q_rx(&dev->mt76, i) {
+ if (mtk_wed_device_active(wed) &&
-+ ((dev->mt76.q_rx[i].flags & MT_QFLAG_RRO) ||
-+ dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE))
++ (mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]) ||
++ mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i])))
+ continue;
+
- mt76_queue_reset(dev, &dev->mt76.q_rx[i], false);
+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
}
diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 3a89013c..d1082e89 100644
+index 60ca23b..22cff71 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -2002,6 +2002,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+@@ -1762,6 +1762,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
/* disable all tx/rx napi */
mt76_worker_disable(&dev->mt76.tx_worker);
mt76_for_each_q_rx(mdev, i) {
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ (mdev->q_rx[i].flags & MT_QFLAG_RRO))
++ mt76_queue_is_wed_rro(&mdev->q_rx[i]))
+ continue;
+
if (mdev->q_rx[i].ndesc)
napi_disable(&dev->mt76.napi[i]);
}
-@@ -2015,6 +2019,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+@@ -1775,6 +1779,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ (mdev->q_rx[i].flags & MT_QFLAG_RRO))
++ mt76_queue_is_wed_rro(&mdev->q_rx[i]))
+ continue;
+
if (mdev->q_rx[i].ndesc) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
-@@ -2189,6 +2197,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
+@@ -1949,6 +1957,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
wiphy_name(dev->mt76.hw->wiphy));
+
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
-+ mtk_wed_device_stop(&dev->mt76.mmio.wed_ext);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
++ mtk_wed_device_stop(&dev->mt76.mmio.wed_hif2);
+
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ mtk_wed_device_stop(&dev->mt76.mmio.wed);
@@ -167,14 +143,14 @@
ieee80211_stop_queues(mt76_hw(dev));
if (phy2)
ieee80211_stop_queues(phy2->mt76->hw);
-@@ -2212,8 +2227,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
+@@ -1972,8 +1987,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
cancel_delayed_work_sync(&phy3->mt76->mac_work);
}
mt76_worker_disable(&dev->mt76.tx_worker);
- mt76_for_each_q_rx(&dev->mt76, i)
+ mt76_for_each_q_rx(&dev->mt76, i) {
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ (dev->mt76.q_rx[i].flags & MT_QFLAG_RRO))
++ mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
+ continue;
+
napi_disable(&dev->mt76.napi[i]);
@@ -182,9 +158,9 @@
napi_disable(&dev->mt76.tx_napi);
mutex_lock(&dev->mt76.mutex);
-@@ -2236,6 +2256,29 @@ void mt7996_mac_reset_work(struct work_struct *work)
- /* enable dma tx/rx and interrupt */
- __mt7996_dma_enable(dev, false, false);
+@@ -1996,6 +2016,27 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ /* enable DMA Tx/Tx and interrupt */
+ mt7996_dma_start(dev, false, false);
+
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
@@ -202,29 +178,27 @@
+ mt7996_irq_disable(dev, 0);
+ }
+
-+ if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
-+ mt76_wr(dev, MT_INT1_MASK_CSR,
-+ dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2);
-+ mtk_wed_device_start(&dev->mt76.mmio.wed_ext,
-+ dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2);
++ if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) {
++ mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TRX_DONE_EXT);
++ mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, MT_INT_TRX_DONE_EXT);
+ }
+
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
-@@ -2245,6 +2288,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+@@ -2005,6 +2046,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
local_bh_disable();
mt76_for_each_q_rx(&dev->mt76, i) {
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
-+ ((dev->mt76.q_rx[i].flags & MT_QFLAG_RRO)))
++ mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
+ continue;
+
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 9960dca7..fe34bb7d 100644
+index 2e395d1..631d905 100644
--- a/mt7996/mmio.c
+++ b/mt7996/mmio.c
@@ -6,9 +6,11 @@
@@ -239,11 +213,11 @@
#include "../trace.h"
#include "../dma.h"
-@@ -297,6 +299,43 @@ unmap:
- mt7996_mmio_wed_release_rx_buf(wed);
- return -ENOMEM;
+@@ -271,6 +273,45 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ return val;
}
-+
+
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
+{
+ struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed);
@@ -280,13 +254,15 @@
+ complete(&dev->mmio.wed_reset_complete);
+}
+
- #endif
-
++#endif
++
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
-@@ -421,6 +460,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- wed->wlan.init_rx_buf = mt7996_mmio_wed_init_rx_buf;
- wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
- wed->wlan.update_wo_rx_stats = NULL;
+ bool hif2, int *irq)
+ {
+@@ -387,6 +428,13 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
+ wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
+ wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
+ if (hif2) {
+ wed->wlan.reset = NULL;
+ wed->wlan.reset_complete = NULL;
@@ -294,10 +270,9 @@
+ wed->wlan.reset = mt7996_mmio_wed_reset;
+ wed->wlan.reset_complete = mt7996_mmio_wed_reset_complete;
+ }
-+
if (mtk_wed_device_attach(wed))
return 0;
--
-2.39.2
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
deleted file mode 100644
index 5897422..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
+++ /dev/null
@@ -1,473 +0,0 @@
-From cc7283ecc1da9d4f62803062466fb5420d2ea766 Mon Sep 17 00:00:00 2001
-From: "sujuan.chen" <sujuan.chen@mediatek.com>
-Date: Thu, 18 May 2023 15:01:47 +0800
-Subject: [PATCH 2007/2008] wifi: mt76: mt7996: reset addr_elem when delete ba
-
-The old addr element info may be used when the signature is not equel to
-0xff, and sta will find error SDP cause the SDP/SDL=0 issue.
-
-Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
----
- mt76.h | 1 +
- mt76_connac_mcu.h | 1 +
- mt7996/init.c | 3 +
- mt7996/mac.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/main.c | 7 +++
- mt7996/mcu.c | 64 +++++++++++++++++++++
- mt7996/mcu.h | 34 +++++++++++
- mt7996/mt7996.h | 32 +++++++++++
- mt7996/regs.h | 5 ++
- 9 files changed, 287 insertions(+)
-
-diff --git a/mt76.h b/mt76.h
-index e4351338..7ebcf432 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -436,6 +436,7 @@ struct mt76_rx_tid {
- u16 nframes;
-
- u8 num;
-+ u8 partial_id;
-
- u8 started:1, stopped:1, timer_pending:1;
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index a53fa138..d74fd2dd 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -1023,6 +1023,7 @@ enum {
- MCU_UNI_EVENT_THERMAL = 0x35,
- MCU_UNI_EVENT_BF = 0x33,
- MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
-+ MCU_UNI_EVENT_RRO = 0x57,
- };
-
- #define MCU_UNI_CMD_EVENT BIT(1)
-diff --git a/mt7996/init.c b/mt7996/init.c
-index d70dcf9f..93262297 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -759,6 +759,9 @@ static int mt7996_rro_init(struct mt7996_dev *dev)
- mt76_wr(dev, MT_RRO_HOST_INT_ENA,
- MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
-
-+ INIT_DELAYED_WORK(&dev->rro.rro_del_work, mt7996_rro_delete_sessions);
-+ INIT_LIST_HEAD(&dev->rro.rro_poll_list);
-+
- /* rro ind cmd queue init */
- return mt7996_dma_rro_init(dev);
- }
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 4fbbc077..3a89013c 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1647,6 +1647,139 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- }
- }
-
-+static struct mt7996_rro_addr *
-+mt7996_rro_get_addr_elem(struct mt7996_dev *dev, u16 seid, u16 sn)
-+{
-+ struct mt7996_rro_cfg *rro = &dev->rro;
-+ u32 idx;
-+ void *addr;
-+
-+ if (seid == rro->particular_se_id) {
-+ addr = rro->particular_session_va;
-+ idx = sn % rro->win_sz;
-+ } else {
-+ addr = rro->addr_elem_alloc_va[seid / MT7996_RRO_SESSION_PER_CR];
-+ idx = (seid % MT7996_RRO_SESSION_PER_CR) * rro->win_sz
-+ + (sn % rro->win_sz);
-+ }
-+ return addr + idx * sizeof(struct mt7996_rro_addr);
-+}
-+
-+static bool mt7996_rro_reset_sessions(struct mt7996_dev *dev,
-+ u16 wcid, u8 partial_id)
-+{
-+ u32 sid = ((wcid & 0x7F) << 3) + partial_id;
-+ u32 value[2];
-+ struct mt7996_rro_ba_session *s;
-+ struct mt7996_rro_addr *elem;
-+ int i;
-+
-+ mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC |
-+ sid >> 1 | 0x200);
-+
-+ if (sid & 0x1) {
-+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
-+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
-+ } else {
-+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
-+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
-+ }
-+
-+ s = (struct mt7996_rro_ba_session *)&value[0];
-+ if (!s->cn && s->ack_sn == s->last_in_sn) {
-+ for (i = 0; i < MT7996_RRO_WIN_SIZE_MAX; i++) {
-+ elem = mt7996_rro_get_addr_elem(dev, sid, i);
-+ elem->signature = 0xff;
-+ }
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void mt7996_rro_delete_sessions(struct work_struct *work)
-+{
-+ struct mt7996_dev *dev;
-+ struct mt7996_rro_ba_session_elem *e;
-+ int elem_nums;
-+ LIST_HEAD(rro_poll_list);
-+
-+ dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
-+ rro.rro_del_work.work);
-+ elem_nums = dev->rro.elem_nums;
-+
-+ spin_lock_bh(&dev->rro.rro_stbl_lock);
-+ list_splice_init(&dev->rro.rro_poll_list, &rro_poll_list);
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+
-+ do {
-+ spin_lock_bh(&dev->rro.rro_stbl_lock);
-+ if (list_empty(&rro_poll_list)) {
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+ break;
-+ }
-+
-+ e = list_first_entry(&rro_poll_list,
-+ struct mt7996_rro_ba_session_elem,
-+ poll_list);
-+ if (!e) {
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+ break;
-+ }
-+ list_del_init(&e->poll_list);
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+
-+ if (mt7996_rro_reset_sessions(dev, e->wlan_idx,
-+ e->partial_id)) {
-+ mt7996_mcu_reset_rro_sessions(dev, e->wlan_idx,
-+ e->tid, e->partial_id);
-+ kfree(e);
-+ dev->rro.elem_nums--;
-+ } else {
-+ spin_lock_bh(&dev->rro.rro_stbl_lock);
-+ list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+ }
-+ elem_nums--;
-+ } while (elem_nums);
-+
-+ if (list_empty(&rro_poll_list))
-+ ieee80211_queue_delayed_work(mt76_hw(dev),
-+ &dev->rro.rro_del_work,
-+ MT7996_WATCHDOG_TIME);
-+}
-+
-+int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
-+ struct mt7996_sta *msta, u8 tidno)
-+{
-+ struct mt76_rx_tid *tid = NULL;
-+ struct mt76_wcid *wcid = &msta->wcid;
-+ struct mt7996_rro_ba_session_elem *e;
-+ u16 idx = msta->wcid.idx;
-+
-+ tid = rcu_dereference(wcid->aggr[tidno]);
-+ if (!tid)
-+ return 0;
-+
-+ e = kzalloc(sizeof(*e), GFP_ATOMIC);
-+ if (!e)
-+ return -ENOMEM;
-+
-+ e->wlan_idx = idx;
-+ e->tid = tidno;
-+ e->partial_id = tid->partial_id;
-+
-+ spin_lock_bh(&dev->rro.rro_stbl_lock);
-+ list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
-+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
-+ dev->rro.elem_nums++;
-+
-+ ieee80211_queue_delayed_work(mt76_hw(dev),
-+ &dev->rro.rro_del_work,
-+ MT7996_WATCHDOG_TIME);
-+ return 0;
-+}
-+
- void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
- {
- struct mt7996_dev *dev = phy->dev;
-@@ -1971,6 +2104,9 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
- if (phy3)
- ieee80211_stop_queues(phy3->mt76->hw);
-
-+ if (dev->rro_support)
-+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
-+
- cancel_delayed_work_sync(&dev->mphy.mac_work);
- if (phy2)
- cancel_delayed_work_sync(&phy2->mt76->mac_work);
-@@ -2062,6 +2198,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
- set_bit(MT76_RESET, &dev->mphy.state);
- set_bit(MT76_MCU_RESET, &dev->mphy.state);
- wake_up(&dev->mt76.mcu.wait);
-+
-+ if (dev->rro_support)
-+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
-+
- cancel_delayed_work_sync(&dev->mphy.mac_work);
- if (phy2) {
- set_bit(MT76_RESET, &phy2->mt76->state);
-diff --git a/mt7996/main.c b/mt7996/main.c
-index cebac4ab..4cb72220 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -119,6 +119,9 @@ static void mt7996_stop(struct ieee80211_hw *hw)
- struct mt7996_dev *dev = mt7996_hw_dev(hw);
- struct mt7996_phy *phy = mt7996_hw_phy(hw);
-
-+ if (dev->rro_support)
-+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
-+
- cancel_delayed_work_sync(&phy->mt76->mac_work);
- cancel_delayed_work_sync(&dev->scs_work);
-
-@@ -797,6 +800,10 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- ret = mt7996_mcu_add_rx_ba(dev, params, true);
- break;
- case IEEE80211_AMPDU_RX_STOP:
-+ if (dev->rro_support) {
-+ ret = mt7996_rro_add_delete_elem(dev, msta,
-+ params->tid);
-+ }
- mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
- ret = mt7996_mcu_add_rx_ba(dev, params, false);
- break;
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 0c01e90b..094f3656 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -476,6 +476,41 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
- phy->throttle_state = n->duty_percent;
- }
-
-+static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
-+{
-+ struct mt7996_mcu_rro_event *event;
-+
-+ if (!dev->rro_support)
-+ return;
-+
-+ event = (struct mt7996_mcu_rro_event*)skb->data;
-+
-+ switch (event->tag) {
-+ case UNI_RRO_BA_SESSION_STATUS: {
-+ struct mt7996_mcu_rro_ba *rro = (struct mt7996_mcu_rro_ba *)skb->data;
-+ u16 idx = rro->wlan_id;
-+ struct mt76_rx_tid *tid;
-+ struct mt76_wcid *wcid;
-+
-+ wcid = rcu_dereference(dev->mt76.wcid[idx]);
-+ if (!wcid || !wcid->sta)
-+ return;
-+
-+ tid = rcu_dereference(wcid->aggr[rro->tid]);
-+ if (!tid)
-+ return;
-+ tid->partial_id = rro->partial_id;
-+
-+ break;
-+ }
-+ default:
-+ dev_info(dev->mt76.dev, "%s: unknown rro event tag %d\n",
-+ __func__, event->tag);
-+ break;
-+ }
-+
-+}
-+
- static void
- mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
- {
-@@ -528,6 +563,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
- mt7996_tm_rf_test_event(dev, skb);
- break;
- #endif
-+ case MCU_UNI_EVENT_RRO:
-+ mt7996_mcu_rx_rro(dev, skb);
-+ break;
- default:
- break;
- }
-@@ -4533,6 +4571,32 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
- sizeof(req), true);
- }
-
-+int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
-+ u16 wcid, u8 tid, u8 pid)
-+{
-+ struct {
-+ /* fixed field */
-+ u8 __rsv[4];
-+
-+ __le16 tag;
-+ __le16 len;
-+ u16 wcid;
-+ u8 tid;
-+ u8 partial_id;
-+ u8 pad[4];
-+ } __packed req = {
-+ .tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
-+ .len = cpu_to_le16(sizeof(req) - 4),
-+ .wcid = wcid,
-+ .tid = tid,
-+ .partial_id = pid,
-+ };
-+
-+ return mt76_mcu_send_msg(&dev->mt76, MCU_WMWA_UNI_CMD(RRO),
-+ &req, sizeof(req), true);
-+}
-+
-+
- int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
- {
- struct mt7996_dev *dev = phy->dev;
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index ec074bc6..10e3799f 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -191,6 +191,38 @@ struct mt7996_mcu_thermal_notify {
- u8 __rsv2[4];
- } __packed;
-
-+struct mt7996_mcu_rro_event {
-+ struct mt7996_mcu_rxd rxd;
-+
-+ u8 __rsv1[4];
-+
-+ __le16 tag;
-+ __le16 len;
-+} __packed;
-+
-+struct mt7996_mcu_rro_ba {
-+ struct mt7996_mcu_rro_event event;
-+
-+ u16 wlan_id;
-+ u8 tid;
-+ u8 partial_id;
-+ __le32 status;
-+}__packed;
-+
-+enum {
-+ UNI_RRO_BA_SESSION_STATUS = 0,
-+ UNI_RRO_BA_SESSION_TBL = 1,
-+ UNI_RRO_BA_SESSION_MAX_NUM
-+};
-+
-+struct mt7996_mcu_rro_del_ba {
-+ struct mt7996_mcu_rro_event event;
-+
-+ u8 wlan_idx;
-+ u8 tid;
-+ u8 __rsv2[2];
-+};
-+
- enum mt7996_chan_mib_offs {
- UNI_MIB_OBSS_AIRTIME = 26,
- UNI_MIB_NON_WIFI_TIME = 27,
-@@ -718,6 +750,8 @@ enum {
- UNI_RRO_GET_BA_SESSION_TABLE,
- UNI_RRO_SET_BYPASS_MODE,
- UNI_RRO_SET_TXFREE_PATH,
-+ UNI_RRO_DEL_BA_SESSION,
-+ UNI_RRO_SET_FLUSH_TIMEOUT
- };
-
- enum{
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index b239c44c..88d42c3a 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -310,6 +310,28 @@ struct mt7996_rro_addr {
- u32 signature : 8;
- };
-
-+struct mt7996_rro_ba_session {
-+ u32 ack_sn :12;
-+ u32 win_sz :3;
-+ u32 bn :1;
-+ u32 last_in_sn :12;
-+ u32 bc :1;
-+ u32 bd :1;
-+ u32 sat :1;
-+ u32 cn :1;
-+ u32 within_cnt :12;
-+ u32 to_sel :3;
-+ u32 rsv :1;
-+ u32 last_in_rxtime :12;
-+};
-+
-+struct mt7996_rro_ba_session_elem {
-+ struct list_head poll_list;
-+ u16 wlan_idx;
-+ u8 tid;
-+ u8 partial_id;
-+};
-+
- struct mt7996_rro_cfg {
- u32 ind_signature;
- void *ba_bitmap_cache_va[MT7996_RRO_BA_BITMAP_CR_CNT];
-@@ -324,6 +346,11 @@ struct mt7996_rro_cfg {
- spinlock_t lock;
- struct list_head pg_addr_cache;
- struct list_head pg_hash_head[MT7996_RRO_MSDU_PG_HASH_SIZE];
-+
-+ struct delayed_work rro_del_work;
-+ spinlock_t rro_stbl_lock;
-+ struct list_head rro_poll_list;
-+ u16 elem_nums;
- };
-
- struct mt7996_phy {
-@@ -670,6 +697,8 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
- int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
- int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
- int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
-+int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
-+ u16 wcid, u8 tid, u8 pid);
- int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
- int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
- int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
-@@ -768,6 +797,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- struct mt76_tx_info *tx_info);
- void mt7996_tx_token_put(struct mt7996_dev *dev);
- int mt7996_dma_rro_init(struct mt7996_dev *dev);
-+void mt7996_rro_delete_sessions(struct work_struct *work);
-+int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
-+ struct mt7996_sta *msta, u8 tid);
- void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb, u32 *info);
- bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
-diff --git a/mt7996/regs.h b/mt7996/regs.h
-index 6624685e..f97c87c9 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -72,6 +72,11 @@ enum base_rev {
- #define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
- #define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
-
-+#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0)
-+#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0)
-+#define MT_RRO_DBG_RD_EXEC BIT(31)
-+
-+#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + _n * 0x4)
-
- #define MT_MCU_INT_EVENT 0x2108
- #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
---
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch
new file mode 100644
index 0000000..2688d54
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch
@@ -0,0 +1,66 @@
+From 50c902b8856af271bc5514d623ad09f7c3f2d880 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Wed, 19 Jul 2023 10:55:09 +0800
+Subject: [PATCH 72/98] wifi: mt76: mt7915: wed: find rx token by physical
+ address
+
+The token id in RxDMAD may be incorrect when it is not the last frame due to
+WED HW bug. Lookup correct token id by physical address in sdp0.
+Add len == 0 check to drop garbage frames
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ dma.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 141a97b..3983ebb 100644
+--- a/dma.c
++++ b/dma.c
+@@ -440,10 +440,33 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ }
+
+ if (mt76_queue_is_wed_rx(q)) {
++ u32 id, find = 0;
+ u32 buf1 = le32_to_cpu(desc->buf1);
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
+- struct mt76_rxwi_cache *r = mt76_rx_token_release(dev, token);
++ struct mt76_rxwi_cache *r;
++
++ if (*more) {
++ spin_lock_bh(&dev->rx_token_lock);
++
++ idr_for_each_entry(&dev->rx_token, r, id) {
++ if (r->dma_addr == le32_to_cpu(desc->buf0)) {
++ find = 1;
++ token = id;
++
++ /* Write correct id back to DMA*/
++ u32p_replace_bits(&buf1, id,
++ MT_DMA_CTL_TOKEN);
++ WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
++ break;
++ }
++ }
+
++ spin_unlock_bh(&dev->rx_token_lock);
++ if (!find)
++ return NULL;
++ }
++
++ r = mt76_rx_token_release(dev, token);
+ if (!r)
+ return NULL;
+
+@@ -965,7 +988,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ if (!data)
+ break;
+
+- if (drop)
++ if (drop || (len == 0))
+ goto free_frag;
+
+ if (q->rx_head)
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch
new file mode 100644
index 0000000..675e4eb
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch
@@ -0,0 +1,77 @@
+From f322c87d1e0634ec86acb5b254220918842132c6 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Wed, 26 Jul 2023 16:33:43 +0800
+Subject: [PATCH 73/98] wifi: mt76: drop packet based on ind_reason
+
+Driver should drop packet which ind_reason is REPEAT and OLDPKT.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c | 15 +++++++++++++--
+ dma.h | 9 +++++++++
+ 2 files changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 3983ebb..69e314a 100644
+--- a/dma.c
++++ b/dma.c
+@@ -435,8 +435,19 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+
+ if (drop) {
+ *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
+- if (ctrl & MT_DMA_CTL_VER_MASK)
+- *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
++ if (ctrl & MT_DMA_CTL_VER_MASK) {
++ switch (le32_get_bits(desc->buf1, MT_DMA_IND_REASON)) {
++ case IND_REASON_REPEAT:
++ *drop = true;
++ break;
++ case IND_REASON_OLDPKT:
++ *drop = !le32_get_bits(desc->info, MT_DMA_INFO_DMA_FRAG);
++ break;
++ default:
++ *drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
++ break;
++ }
++ }
+ }
+
+ if (mt76_queue_is_wed_rx(q)) {
+diff --git a/dma.h b/dma.h
+index 22b79d5..afcbcdd 100644
+--- a/dma.h
++++ b/dma.h
+@@ -23,6 +23,7 @@
+
+ #define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
+ #define MT_DMA_PPE_ENTRY GENMASK(30, 16)
++#define MT_DMA_INFO_DMA_FRAG BIT(9)
+ #define MT_DMA_INFO_PPE_VLD BIT(31)
+
+ #define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
+@@ -31,6 +32,7 @@
+ #define MT_DMA_RRO_EN BIT(13)
+
+ #define MT_DMA_WED_IND_CMD_CNT 8
++#define MT_DMA_IND_REASON GENMASK(15, 12)
+
+ #define MT_DMA_HDR_LEN 4
+ #define MT_RX_INFO_LEN 4
+@@ -66,6 +68,13 @@ enum mt76_mcu_evt_type {
+ EVT_EVENT_DFS_DETECT_RSP,
+ };
+
++enum ind_reason {
++ IND_REASON_NORMAL,
++ IND_REASON_REPEAT,
++ IND_REASON_OLDPKT,
++ IND_REASON_MAX
++};
++
+ int mt76_dma_rx_poll(struct napi_struct *napi, int budget);
+ void mt76_dma_attach(struct mt76_dev *dev);
+ void mt76_dma_cleanup(struct mt76_dev *dev);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch
new file mode 100644
index 0000000..6fe2cea
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch
@@ -0,0 +1,94 @@
+From 531d586b936634fad23651d18d2bbc832692c520 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Fri, 11 Aug 2023 18:26:39 +0800
+Subject: [PATCH 74/98] wifi: mt76: mt7996: add rro timeout setting
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt7996/init.c | 5 +++++
+ mt7996/mcu.c | 11 ++++++++++-
+ mt7996/mt7996.h | 2 +-
+ mt7996/regs.h | 2 ++
+ 4 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 1ece390..51649dd 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -506,6 +506,11 @@ void mt7996_mac_init(struct mt7996_dev *dev)
+ /* rro module init */
+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
+ if (dev->has_rro) {
++ u16 timeout;
++
++ timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_VER1 ? 512 : 128;
++
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
+ mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
+ } else {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index ce38a5e..bebd020 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4626,7 +4626,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev)
+ &req, sizeof(req), false);
+ }
+
+-int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
++int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
+ {
+ struct {
+ u8 __rsv1[4];
+@@ -4648,6 +4648,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ u8 path;
+ u8 __rsv2[3];
+ } __packed txfree_path;
++ struct {
++ u16 flush_one;
++ u16 flush_all;
++ u8 __rsv2[4];
++ } __packed timeout;
+ };
+ } __packed req = {
+ .tag = cpu_to_le16(tag),
+@@ -4664,6 +4669,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ case UNI_RRO_SET_TXFREE_PATH:
+ req.txfree_path.path = val;
+ break;
++ case UNI_RRO_SET_FLUSH_TIMEOUT:
++ req.timeout.flush_one = val;
++ req.timeout.flush_all = val * 2;
++ break;
+ default:
+ return -EINVAL;
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index af67c59..06e00f4 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -676,7 +676,7 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+ u16 rate_idx, bool beacon);
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+-int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
++int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val);
+ int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev, u16 seid);
+ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
+ int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index a0b5270..77a2f9d 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -667,6 +667,8 @@ enum offs_rev {
+ #define MT_PAD_GPIO_ADIE_NUM_7992 BIT(15)
+
+ #define MT_HW_REV 0x70010204
++#define MT_HW_VER1 0x8a00
++
+ #define MT_WF_SUBSYS_RST 0x70028600
+
+ /* PCIE MAC */
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch
new file mode 100644
index 0000000..fec02ea
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch
@@ -0,0 +1,84 @@
+From 39a1bb49d83141f79bf329fdd68e82bb77f5d0a2 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 20 Jul 2023 10:25:50 +0800
+Subject: [PATCH 75/98] wifi: mt76: mt7996: add dma mask limitation
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c | 4 ++--
+ mmio.c | 3 ++-
+ mt7996/mmio.c | 8 --------
+ mt7996/pci.c | 2 +-
+ 4 files changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 69e314a..7616921 100644
+--- a/dma.c
++++ b/dma.c
+@@ -494,7 +494,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ } else {
+ struct mt76_queue_buf qbuf;
+
+- buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC | GFP_DMA32);
+ if (!buf)
+ return NULL;
+
+@@ -713,7 +713,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ if (mt76_queue_is_wed_rro_ind(q))
+ goto done;
+
+- buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC | GFP_DMA32);
+ if (!buf)
+ break;
+
+diff --git a/mmio.c b/mmio.c
+index f7495f6..22629af 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -150,7 +150,8 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ if (!r)
+ goto unmap;
+
+- ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length, GFP_ATOMIC);
++ ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length,
++ GFP_ATOMIC | GFP_DMA32);
+ if (!ptr) {
+ mt76_put_rxwi(dev, r);
+ goto unmap;
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 631d905..38b8843 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -442,14 +442,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ *irq = wed->irq;
+ dev->mt76.dma_dev = wed->dev;
+
+- ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
+- if (ret)
+- return ret;
+-
+- ret = dma_set_coherent_mask(wed->dev, DMA_BIT_MASK(32));
+- if (ret)
+- return ret;
+-
+ return 1;
+ #else
+ return 0;
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 2bb707d..0024929 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -111,7 +111,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+
+ pci_set_master(pdev);
+
+- ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
new file mode 100644
index 0000000..3295f14
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
@@ -0,0 +1,122 @@
+From d97655d3fe3ddf2bbd508de52e207bc91d0115e2 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Fri, 18 Aug 2023 10:17:08 +0800
+Subject: [PATCH 76/98] wifi: mt76: mt7996: add per bss statistic info
+
+Whenever WED is enabled, unicast traffic might run through HW path.
+As a result, we need to count them using WM event.
+Broadcast and multicast traffic on the other hand, will be counted in mac80211
+as they always go through SW path and thus mac80211 can always see and count them.
+
+| | Tx | Rx |
+|---------|--------------------------------|---------------------------|
+| Unicast | mt76 | mt76 |
+| | __mt7996_stat_to_netdev() | __mt7996_stat_to_netdev() |
+|---------|--------------------------------|---------------------------|
+| BMCast | mac80211 | mac80211 |
+| | __ieee80211_subif_start_xmit() | ieee80211_deliver_skb() |
+---
+ mt7996/init.c | 1 +
+ mt7996/main.c | 1 +
+ mt7996/mcu.c | 40 +++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 51649dd..20e14e7 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -378,6 +378,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
++ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STAS_COUNT);
+
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d27275a..2e0b1f1 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -251,6 +251,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
+ mvif->sta.wcid.phy_idx = band_idx;
+ mvif->sta.wcid.hw_key_idx = -1;
+ mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
++ mvif->sta.vif = mvif;
+ mt76_wcid_init(&mvif->sta.wcid);
+
+ mt7996_mac_wtbl_update(dev, idx,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index bebd020..b2cb627 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -592,6 +592,27 @@ static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
+
+ }
+
++static inline void __mt7996_stat_to_netdev(struct mt76_phy *mphy,
++ struct mt76_wcid *wcid,
++ u32 tx_bytes, u32 rx_bytes,
++ u32 tx_packets, u32 rx_packets)
++{
++ struct mt7996_sta *msta;
++ struct ieee80211_vif *vif;
++ struct wireless_dev *wdev;
++
++ if (wiphy_ext_feature_isset(mphy->hw->wiphy,
++ NL80211_EXT_FEATURE_STAS_COUNT)) {
++ msta = container_of(wcid, struct mt7996_sta, wcid);
++ vif = container_of((void *)msta->vif, struct ieee80211_vif,
++ drv_priv);
++ wdev = ieee80211_vif_to_wdev(vif);
++
++ dev_sw_netstats_tx_add(wdev->netdev, tx_packets, tx_bytes);
++ dev_sw_netstats_rx_add(wdev->netdev, rx_packets, rx_bytes);
++ }
++}
++
+ static void
+ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -607,7 +628,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ u16 wlan_idx;
+ struct mt76_wcid *wcid;
+ struct mt76_phy *mphy;
+- u32 tx_bytes, rx_bytes;
++ u32 tx_bytes, rx_bytes, tx_packets, rx_packets;
+
+ switch (le16_to_cpu(res->tag)) {
+ case UNI_ALL_STA_TXRX_RATE:
+@@ -635,6 +656,9 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ wcid->stats.tx_bytes += tx_bytes;
+ wcid->stats.rx_bytes += rx_bytes;
+
++ __mt7996_stat_to_netdev(mphy, wcid,
++ tx_bytes, rx_bytes, 0, 0);
++
+ ieee80211_tpt_led_trig_tx(mphy->hw, tx_bytes);
+ ieee80211_tpt_led_trig_rx(mphy->hw, rx_bytes);
+ }
+@@ -646,10 +670,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ if (!wcid)
+ break;
+
+- wcid->stats.tx_packets +=
+- le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
+- wcid->stats.rx_packets +=
+- le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
++ mphy = mt76_dev_phy(&dev->mt76, wcid->phy_idx);
++
++ tx_packets = le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
++ rx_packets = le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
++
++ wcid->stats.tx_packets += tx_packets;
++ wcid->stats.rx_packets += rx_packets;
++
++ __mt7996_stat_to_netdev(mphy, wcid, 0, 0,
++ tx_packets, rx_packets);
+ break;
+ default:
+ break;
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch
new file mode 100644
index 0000000..8dd2d61
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch
@@ -0,0 +1,234 @@
+From bd93ad7026e316307453438f4b7bce59e30bf03e Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Wed, 7 Jun 2023 14:11:28 +0800
+Subject: [PATCH 77/98] wifi: mt76: mt7996: support TX/RX for Kite without WED
+ and RRO
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac3_mac.h | 3 ++-
+ mt7996/dma.c | 61 +++++++++++++++++++++++++++++++++++++---------
+ mt7996/init.c | 10 ++++++--
+ mt7996/mac.c | 7 ++++--
+ mt7996/mt7996.h | 4 +--
+ mt7996/regs.h | 4 +--
+ 6 files changed, 68 insertions(+), 21 deletions(-)
+
+diff --git a/mt76_connac3_mac.h b/mt76_connac3_mac.h
+index 7402de2..3fd46ae 100644
+--- a/mt76_connac3_mac.h
++++ b/mt76_connac3_mac.h
+@@ -244,7 +244,8 @@ enum tx_mgnt_type {
+ #define MT_TXD6_TX_RATE GENMASK(21, 16)
+ #define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
+ #define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
+-#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
++#define MT_TXD6_MSDU_CNT_MT7996 GENMASK(9, 4)
++#define MT_TXD6_MSDU_CNT_MT7992 GENMASK(15, 10)
+ #define MT_TXD6_DIS_MAT BIT(3)
+ #define MT_TXD6_DAS BIT(2)
+ #define MT_TXD6_AMSDU_CAP BIT(1)
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index b2c7ae6..1163550 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -57,13 +57,21 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+ RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7996_RXQ_MCU_WM);
+ RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7996_RXQ_MCU_WA);
+
+- /* band0/band1 */
++ /* MT7996 band0/band1
++ * MT7992 band0
++ */
+ RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7996_RXQ_BAND0);
+ RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN, MT7996_RXQ_MCU_WA_MAIN);
+
+- /* band2 */
+- RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
+- RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
++ if (is_mt7996(&dev->mt76)) {
++ /* MT7996 band2 */
++ RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
++ RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
++ } else {
++ /* MT7992 band1 */
++ RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1);
++ RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT, MT7996_RXQ_MCU_WA_EXT);
++ }
+
+ if (dev->has_rro) {
+ /* band0 */
+@@ -90,8 +98,12 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+
+ /* data tx queue */
+ TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
+- TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
+- TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
++ if (is_mt7996(&dev->mt76)) {
++ TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
++ TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
++ } else {
++ TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
++ }
+
+ /* mcu tx queue */
+ MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM);
+@@ -123,10 +135,15 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x2));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x2));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x2));
+- mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x2));
++ if (is_mt7996(&dev->mt76))
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x2));
++ else
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs, PREFETCH(0x2));
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
+- mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x10));
+-
++ if (is_mt7996(&dev->mt76))
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x10));
++ else
++ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs, PREFETCH(0x10));
+ if (dev->has_rro) {
+ mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
+ PREFETCH(0x10));
+@@ -488,7 +505,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
+- /* rx data queue for band0 and band1 */
++ /* rx data queue for band0 and MT7996 band1 */
+ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
+ dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0);
+ dev->mt76.q_rx[MT_RXQ_MAIN].wed = wed;
+@@ -517,7 +534,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ return ret;
+
+ if (mt7996_band_valid(dev, MT_BAND2)) {
+- /* rx data queue for band2 */
++ /* rx data queue for MT7996 band2 */
+ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
+ if (mtk_wed_device_active(wed_hif2) && mtk_wed_get_rx_capa(wed_hif2)) {
+ dev->mt76.q_rx[MT_RXQ_BAND2].flags = MT_WED_Q_RX(0);
+@@ -531,7 +548,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
+- /* tx free notify event from WA for band2
++ /* tx free notify event from WA for MT7996 band2
+ * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
+ */
+ if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) {
+@@ -546,6 +563,26 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ MT_RXQ_RING_BASE(MT_RXQ_BAND2_WA));
+ if (ret)
+ return ret;
++ } else if (mt7996_band_valid(dev, MT_BAND1)) {
++ /* rx data queue for MT7992 band1 */
++ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs;
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
++ MT_RXQ_ID(MT_RXQ_BAND1),
++ MT7996_RX_RING_SIZE,
++ MT_RX_BUF_SIZE,
++ rx_base);
++ if (ret)
++ return ret;
++
++ /* tx free notify event from WA for MT7992 band1 */
++ rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs;
++ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
++ MT_RXQ_ID(MT_RXQ_BAND1_WA),
++ MT7996_RX_MCU_RING_SIZE,
++ MT_RX_BUF_SIZE,
++ rx_base);
++ if (ret)
++ return ret;
+ }
+
+ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 20e14e7..d539af0 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -505,7 +505,12 @@ void mt7996_mac_init(struct mt7996_dev *dev)
+ mt76_rmw_field(dev, MT_DMA_TCRF1(2), MT_DMA_TCRF1_QIDX, 0);
+
+ /* rro module init */
+- mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
++ if (is_mt7996(&dev->mt76))
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
++ else
++ mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
++ dev->hif2 ? 7 : 0);
++
+ if (dev->has_rro) {
+ u16 timeout;
+
+@@ -562,7 +567,8 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ if (phy)
+ return 0;
+
+- if (band == MT_BAND2 && dev->hif2) {
++ if ((is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) ||
++ (is_mt7992(&dev->mt76) && band == MT_BAND1 && dev->hif2)) {
+ hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+ wed = &dev->mt76.mmio.wed_hif2;
+ }
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 22cff71..a92298d 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -878,8 +878,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ val |= MT_TXD5_TX_STATUS_HOST;
+ txwi[5] = cpu_to_le32(val);
+
+- val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
+- FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
++ val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
++ if (is_mt7996(&dev->mt76))
++ val |= FIELD_PREP(MT_TXD6_MSDU_CNT_MT7996, 1);
++ else
++ val |= FIELD_PREP(MT_TXD6_MSDU_CNT_MT7992, 1);
+ txwi[6] = cpu_to_le32(val);
+ txwi[7] = 0;
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 06e00f4..4333d51 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -152,10 +152,10 @@ enum mt7996_rxq_id {
+ MT7996_RXQ_MCU_WM = 0,
+ MT7996_RXQ_MCU_WA,
+ MT7996_RXQ_MCU_WA_MAIN = 2,
+- MT7996_RXQ_MCU_WA_EXT = 2,/* unused */
++ MT7996_RXQ_MCU_WA_EXT = 3, /* Only used by MT7992. */
+ MT7996_RXQ_MCU_WA_TRI = 3,
+ MT7996_RXQ_BAND0 = 4,
+- MT7996_RXQ_BAND1 = 4,/* unused */
++ MT7996_RXQ_BAND1 = 5, /* Only used by MT7992. */
+ MT7996_RXQ_BAND2 = 5,
+ MT7996_RXQ_RRO_BAND0 = 8,
+ MT7996_RXQ_RRO_BAND1 = 8,/* unused */
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 77a2f9d..c9e90e3 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -491,12 +491,12 @@ enum offs_rev {
+ #define MT_INT1_MASK_CSR MT_WFDMA0_PCIE1(0x204)
+
+ #define MT_INT_RX_DONE_BAND0 BIT(12)
+-#define MT_INT_RX_DONE_BAND1 BIT(12)
++#define MT_INT_RX_DONE_BAND1 BIT(13) /* Only used by MT7992. */
+ #define MT_INT_RX_DONE_BAND2 BIT(13)
+ #define MT_INT_RX_DONE_WM BIT(0)
+ #define MT_INT_RX_DONE_WA BIT(1)
+ #define MT_INT_RX_DONE_WA_MAIN BIT(2)
+-#define MT_INT_RX_DONE_WA_EXT BIT(2)
++#define MT_INT_RX_DONE_WA_EXT BIT(3) /* Only used by MT7992. */
+ #define MT_INT_RX_DONE_WA_TRI BIT(3)
+ #define MT_INT_RX_TXFREE_MAIN BIT(17)
+ #define MT_INT_RX_TXFREE_TRI BIT(15)
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch
new file mode 100644
index 0000000..a581775
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch
@@ -0,0 +1,528 @@
+From dda3205c68ab3b38945f0066be5fc95ba067f3af Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Mon, 11 Sep 2023 16:35:15 +0800
+Subject: [PATCH 78/98] wifi: mt76: mt7996: add support for HW-ATF
+ initialization
+
+---
+ mt7996/init.c | 43 ++++++++
+ mt7996/mcu.c | 263 +++++++++++++++++++++++++++++++++++++++++++-----
+ mt7996/mcu.h | 1 +
+ mt7996/mt7996.h | 94 +++++++++++++++++
+ 4 files changed, 376 insertions(+), 25 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index d539af0..d1db1d7 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -553,6 +553,37 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
+ return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
+ }
+
++static int mt7996_vow_init(struct mt7996_phy *phy)
++{
++ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
++ int ret;
++
++ vow->atf_enable = true;
++ vow->watf_enable = false;
++ vow->max_deficit = 64;
++ vow->sch_type = VOW_SCH_TYPE_FOLLOW_POLICY;
++ vow->sch_policy = VOW_SCH_POLICY_SRR;
++
++ vow->drr_quantum[0] = VOW_DRR_QUANTUM_L0;
++ vow->drr_quantum[1] = VOW_DRR_QUANTUM_L1;
++ vow->drr_quantum[2] = VOW_DRR_QUANTUM_L2;
++ vow->drr_quantum[3] = VOW_DRR_QUANTUM_L3;
++ vow->drr_quantum[4] = VOW_DRR_QUANTUM_L4;
++ vow->drr_quantum[5] = VOW_DRR_QUANTUM_L5;
++ vow->drr_quantum[6] = VOW_DRR_QUANTUM_L6;
++ vow->drr_quantum[7] = VOW_DRR_QUANTUM_L7;
++
++ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND);
++ if (ret)
++ return ret;
++
++ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL);
++ if (ret)
++ return ret;
++
++ return mt7996_mcu_set_vow_feature_ctrl(phy);
++}
++
+ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ enum mt76_band_id band)
+ {
+@@ -626,6 +657,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ if (ret)
+ goto error;
+
++ if (mt7996_vow_should_enable(dev)) {
++ ret = mt7996_vow_init(phy);
++ if (ret)
++ goto error;
++ }
++
+ ret = mt7996_init_debugfs(phy);
+ if (ret)
+ goto error;
+@@ -1315,6 +1352,12 @@ int mt7996_register_device(struct mt7996_dev *dev)
+
+ dev->recovery.hw_init_done = true;
+
++ if (mt7996_vow_should_enable(dev)) {
++ ret = mt7996_vow_init(&dev->phy);
++ if (ret)
++ goto error;
++ }
++
+ ret = mt7996_init_debugfs(&dev->phy);
+ if (ret)
+ goto error;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index b2cb627..1915a22 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2147,34 +2147,35 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ }
+
+ static int
+-mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+- struct ieee80211_sta *sta)
++mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
+ {
+-#define MT_STA_BSS_GROUP 1
+- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+- struct mt7996_sta *msta;
+- struct {
+- u8 __rsv1[4];
++ struct mt7996_vow_sta_ctrl *vow = &msta->vow;
++ u8 omac_idx = msta->vif->mt76.omac_idx;
++ int ret;
+
+- __le16 tag;
+- __le16 len;
+- __le16 wlan_idx;
+- u8 __rsv2[2];
+- __le32 action;
+- __le32 val;
+- u8 __rsv3[8];
+- } __packed req = {
+- .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
+- .len = cpu_to_le16(sizeof(req) - 4),
+- .action = cpu_to_le32(MT_STA_BSS_GROUP),
+- .val = cpu_to_le32(mvif->mt76.idx % 16),
+- };
++ /* Assignment of STA BSS group index aligns FW.
++ * Each band has its own BSS group bitmap space.
++ * 0: BSS 0
++ * 4..18: BSS 0x11..0x1f
++ */
++ vow->bss_grp_idx = (omac_idx <= HW_BSSID_MAX)
++ ? omac_idx
++ : HW_BSSID_MAX + omac_idx - EXT_BSSID_START;
++ vow->paused = false;
++ vow->drr_quantum[IEEE80211_AC_VO] = VOW_DRR_QUANTUM_IDX0;
++ vow->drr_quantum[IEEE80211_AC_VI] = VOW_DRR_QUANTUM_IDX1;
++ vow->drr_quantum[IEEE80211_AC_BE] = VOW_DRR_QUANTUM_IDX2;
++ vow->drr_quantum[IEEE80211_AC_BK] = VOW_DRR_QUANTUM_IDX2;
++
++ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
++ if (ret)
++ return ret;
+
+- msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta;
+- req.wlan_idx = cpu_to_le16(msta->wcid.idx);
++ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_PAUSE);
++ if (ret)
++ return ret;
+
+- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
+- sizeof(req), true);
++ return mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_ALL);
+ }
+
+ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -2228,7 +2229,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
+ }
+
+- ret = mt7996_mcu_add_group(dev, vif, sta);
++ ret = mt7996_mcu_sta_init_vow(mvif->phy, msta);
+ if (ret) {
+ dev_kfree_skb(skb);
+ return ret;
+@@ -5027,6 +5028,218 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ MCU_WM_UNI_CMD(TXPOWER), true);
+ }
+
++int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
++ enum vow_drr_ctrl_id id)
++{
++ struct mt7996_vow_sta_ctrl *vow = msta ? &msta->vow : NULL;
++ u32 val = 0;
++ struct {
++ u8 __rsv1[4];
++
++ __le16 tag;
++ __le16 len;
++ __le16 wlan_idx;
++ u8 band_idx;
++ u8 wmm_idx;
++ __le32 ctrl_id;
++
++ union {
++ __le32 val;
++ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
++ };
++
++ u8 __rsv2[3];
++ u8 omac_idx;
++ } __packed req = {
++ .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .wlan_idx = cpu_to_le16(msta ? msta->wcid.idx : 0),
++ .band_idx = phy->mt76->band_idx,
++ .wmm_idx = msta ? msta->vif->mt76.wmm_idx : 0,
++ .ctrl_id = cpu_to_le32(id),
++ .omac_idx = msta ? msta->vif->mt76.omac_idx : 0
++ };
++
++ switch (id) {
++ case VOW_DRR_CTRL_STA_ALL:
++ val |= FIELD_PREP(MT7996_DRR_STA_BSS_GRP_MASK, vow->bss_grp_idx);
++ val |= FIELD_PREP(MT7996_DRR_STA_AC0_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BK]);
++ val |= FIELD_PREP(MT7996_DRR_STA_AC1_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BE]);
++ val |= FIELD_PREP(MT7996_DRR_STA_AC2_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VI]);
++ val |= FIELD_PREP(MT7996_DRR_STA_AC3_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VO]);
++ req.val = cpu_to_le32(val);
++ break;
++ case VOW_DRR_CTRL_STA_BSS_GROUP:
++ req.val = cpu_to_le32(vow->bss_grp_idx);
++ break;
++ case VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND:
++ req.val = cpu_to_le32(phy->dev->vow.max_deficit);
++ break;
++ case VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL:
++ memcpy(req.drr_quantum, phy->dev->vow.drr_quantum, VOW_DRR_QUANTUM_NUM);
++ break;
++ case VOW_DRR_CTRL_STA_PAUSE:
++ req.val = cpu_to_le32(vow->paused);
++ break;
++ default:
++ dev_err(phy->dev->mt76.dev, "Unknown VoW DRR Control ID: %u\n", id);
++ return -EINVAL;
++ }
++
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
++ &req, sizeof(req), true);
++}
++
++int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy)
++{
++ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
++ struct {
++ u8 __rsv1[4];
++
++ __le16 tag;
++ __le16 len;
++
++ /* DW0 */
++ __le16 apply_bwc_enable_per_grp;
++ __le16 apply_bwc_refill_period : 1;
++ __le16 __rsv2 : 3;
++ __le16 apply_band1_search_rule : 1;
++ __le16 apply_band0_search_rule : 1;
++ __le16 __rsv3 : 3;
++ __le16 apply_watf_enable : 1;
++ __le16 __rsv4 : 2;
++ __le16 apply_grp_no_change_in_txop : 1;
++ __le16 apply_atf_enable : 1;
++ __le16 apply_bwc_token_refill_enable : 1;
++ __le16 apply_bwc_enable : 1;
++
++ /* DW1 */
++ __le16 apply_bwc_check_time_token_per_grp;
++ __le16 __rsv5;
++
++ /* DW2 */
++ __le16 apply_bwc_check_len_token_per_grp;
++ __le16 __rsv6;
++
++ /* DW3 */
++ u8 band_idx;
++ u8 __rsv7[3];
++
++ /* DW4 */
++ __le32 __rsv8;
++
++ /* DW5 */
++ __le16 bwc_enable_per_grp;
++ __le16 bwc_refill_period : 3;
++ __le16 __rsv9 : 1;
++ __le16 band1_search_rule : 1;
++ __le16 band0_search_rule : 1;
++ __le16 __rsv10 : 3;
++ __le16 watf_enable : 1;
++ __le16 __rsv11 : 2;
++ __le16 grp_no_change_in_txop : 1;
++ __le16 atf_enable : 1;
++ __le16 bwc_token_refill_enable : 1;
++ __le16 bwc_enable : 1;
++
++ /* DW6 */
++ __le16 bwc_check_time_token_per_grp;
++ __le16 __rsv12;
++
++ /* DW7 */
++ __le16 bwc_check_len_token_per_grp;
++ __le16 __rsv13;
++
++ /* DW8 */
++ __le32 apply_atf_rts_sta_lock : 1;
++ __le32 atf_rts_sta_lock : 1;
++ __le32 apply_atf_keep_quantum : 1;
++ __le32 atf_keep_quantum : 1;
++ __le32 apply_tx_cnt_mode_ctrl : 1;
++ __le32 tx_cnt_mode_ctrl : 4;
++ __le32 apply_tx_measure_mode_enable : 1;
++ __le32 tx_measure_mode_enable : 1;
++ __le32 apply_backoff_ctrl : 1;
++ __le32 backoff_bound_enable : 1;
++ __le32 backoff_bound : 5;
++ __le32 apply_atf_rts_fail_charge : 1;
++ __le32 atf_rts_fail_charge : 1;
++ __le32 apply_zero_eifs : 1;
++ __le32 zero_eifs : 1;
++ __le32 apply_rx_rifs_enable : 1;
++ __le32 rx_rifs_enable : 1;
++ __le32 apply_vow_ctrl : 1;
++ __le32 vow_ctrl_val : 1;
++ __le32 vow_ctrl_bit : 5;
++ __le32 __rsv14 : 1;
++
++ /* DW9 */
++ __le32 apply_spl_sta_num : 1;
++ __le32 spl_sta_num : 3;
++ __le32 dbg_lvl : 2;
++ __le32 apply_atf_sch_ctrl : 1;
++ __le32 atf_sch_type : 2;
++ __le32 atf_sch_policy : 2;
++ __le32 __rsv15 : 21;
++ } __packed req = {
++ .tag = cpu_to_le16(UNI_VOW_FEATURE_CTRL),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ /* DW0 */
++ .apply_bwc_enable_per_grp = cpu_to_le16(0xffff),
++ .apply_bwc_refill_period = true,
++ .apply_band1_search_rule = true,
++ .apply_band0_search_rule = true,
++ .apply_watf_enable = true,
++ .apply_grp_no_change_in_txop = true,
++ .apply_atf_enable = true,
++ .apply_bwc_token_refill_enable = true,
++ .apply_bwc_enable = true,
++ /* DW1 */
++ .apply_bwc_check_time_token_per_grp = cpu_to_le16(0xffff),
++ /* DW2 */
++ .apply_bwc_check_len_token_per_grp = cpu_to_le16(0xffff),
++ /* DW3 */
++ .band_idx = phy->mt76->band_idx,
++ /* DW5 */
++ .bwc_enable_per_grp = cpu_to_le16(0xffff),
++ .bwc_refill_period = VOW_REFILL_PERIOD_32US,
++ .band1_search_rule = VOW_SEARCH_WMM_FIRST,
++ .band0_search_rule = VOW_SEARCH_WMM_FIRST,
++ .watf_enable = vow->watf_enable,
++ .grp_no_change_in_txop = true,
++ .atf_enable = vow->atf_enable,
++ .bwc_token_refill_enable = true,
++ .bwc_enable = false,
++ /* DW6 */
++ .bwc_check_time_token_per_grp = cpu_to_le16(0x0),
++ /* DW7 */
++ .bwc_check_len_token_per_grp = cpu_to_le16(0x0),
++ /* DW8 */
++ .apply_atf_rts_sta_lock = false,
++ .apply_atf_keep_quantum = true,
++ .atf_keep_quantum = true,
++ .apply_tx_cnt_mode_ctrl = false,
++ .apply_tx_measure_mode_enable = false,
++ .apply_backoff_ctrl = false,
++ .apply_atf_rts_fail_charge = false,
++ .apply_zero_eifs = false,
++ .apply_rx_rifs_enable = false,
++ .apply_vow_ctrl = true,
++ .vow_ctrl_val = true,
++ /* Reset DRR table when SER occurs. */
++ .vow_ctrl_bit = 26,
++ /* DW9 */
++ .apply_spl_sta_num = false,
++ .dbg_lvl = 0,
++ .apply_atf_sch_ctrl = true,
++ .atf_sch_type = vow->sch_type,
++ .atf_sch_policy = vow->sch_policy
++ };
++
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
++ &req, sizeof(req), true);
++}
++
+ #ifdef CONFIG_MTK_VENDOR
+ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+ {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 0aa68f7..fb81645 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -860,6 +860,7 @@ enum {
+
+ enum {
+ UNI_VOW_DRR_CTRL,
++ UNI_VOW_FEATURE_CTRL,
+ UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
+ UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
+ UNI_VOW_RED_ENABLE = 0x18,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 4333d51..ba73520 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -107,6 +107,12 @@
+ #define MT7996_RX_MSDU_PAGE_SIZE (128 + \
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
+
++#define MT7996_DRR_STA_BSS_GRP_MASK GENMASK(5, 0)
++#define MT7996_DRR_STA_AC0_QNTM_MASK GENMASK(10, 8)
++#define MT7996_DRR_STA_AC1_QNTM_MASK GENMASK(14, 12)
++#define MT7996_DRR_STA_AC2_QNTM_MASK GENMASK(18, 16)
++#define MT7996_DRR_STA_AC3_QNTM_MASK GENMASK(22, 20)
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -187,6 +193,79 @@ struct mt7996_twt_flow {
+
+ DECLARE_EWMA(avg_signal, 10, 8)
+
++enum {
++ VOW_SEARCH_AC_FIRST,
++ VOW_SEARCH_WMM_FIRST
++};
++
++enum {
++ VOW_REFILL_PERIOD_1US,
++ VOW_REFILL_PERIOD_2US,
++ VOW_REFILL_PERIOD_4US,
++ VOW_REFILL_PERIOD_8US,
++ VOW_REFILL_PERIOD_16US,
++ VOW_REFILL_PERIOD_32US,
++ VOW_REFILL_PERIOD_64US,
++ VOW_REFILL_PERIOD_128US
++};
++
++/* Default DRR airtime quantum of each level */
++enum {
++ VOW_DRR_QUANTUM_L0 = 6,
++ VOW_DRR_QUANTUM_L1 = 12,
++ VOW_DRR_QUANTUM_L2 = 16,
++ VOW_DRR_QUANTUM_L3 = 20,
++ VOW_DRR_QUANTUM_L4 = 24,
++ VOW_DRR_QUANTUM_L5 = 28,
++ VOW_DRR_QUANTUM_L6 = 32,
++ VOW_DRR_QUANTUM_L7 = 36
++};
++
++enum {
++ VOW_DRR_QUANTUM_IDX0,
++ VOW_DRR_QUANTUM_IDX1,
++ VOW_DRR_QUANTUM_IDX2,
++ VOW_DRR_QUANTUM_IDX3,
++ VOW_DRR_QUANTUM_IDX4,
++ VOW_DRR_QUANTUM_IDX5,
++ VOW_DRR_QUANTUM_IDX6,
++ VOW_DRR_QUANTUM_IDX7,
++ VOW_DRR_QUANTUM_NUM
++};
++
++enum {
++ VOW_SCH_TYPE_FOLLOW_POLICY,
++ VOW_SCH_TYPE_FOLLOW_HW
++};
++
++enum {
++ VOW_SCH_POLICY_SRR, /* Shared Round-Robin */
++ VOW_SCH_POLICY_WRR /* Weighted Round-Robin */
++};
++
++enum vow_drr_ctrl_id {
++ VOW_DRR_CTRL_STA_ALL,
++ VOW_DRR_CTRL_STA_BSS_GROUP,
++ VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND = 0x10,
++ VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL = 0x28,
++ VOW_DRR_CTRL_STA_PAUSE = 0x30
++};
++
++struct mt7996_vow_ctrl {
++ bool atf_enable;
++ bool watf_enable;
++ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
++ u8 max_deficit;
++ u8 sch_type;
++ u8 sch_policy;
++};
++
++struct mt7996_vow_sta_ctrl {
++ bool paused;
++ u8 bss_grp_idx;
++ u8 drr_quantum[IEEE80211_NUM_ACS];
++};
++
+ struct mt7996_sta {
+ struct mt76_wcid wcid; /* must be first */
+
+@@ -206,6 +285,8 @@ struct mt7996_sta {
+ u8 flowid_mask;
+ struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
+ } twt;
++
++ struct mt7996_vow_sta_ctrl vow;
+ };
+
+ struct mt7996_vif {
+@@ -470,6 +551,7 @@ struct mt7996_dev {
+
+ u8 wtbl_size_group;
+
++ struct mt7996_vow_ctrl vow;
+ #ifdef CONFIG_MTK_DEBUG
+ u16 wlan_idx;
+ struct {
+@@ -697,6 +779,10 @@ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
+
++int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
++ enum vow_drr_ctrl_id id);
++int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy);
++
+ static inline u16 mt7996_eeprom_size(struct mt7996_dev *dev)
+ {
+ return is_mt7996(&dev->mt76) ? MT7996_EEPROM_SIZE : MT7992_EEPROM_SIZE;
+@@ -749,6 +835,14 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
+ return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
+ }
+
++static inline bool
++mt7996_vow_should_enable(struct mt7996_dev *dev)
++{
++ return !wiphy_ext_feature_isset(mt76_hw(dev)->wiphy,
++ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS) ||
++ mtk_wed_device_active(&dev->mt76.mmio.wed);
++}
++
+ void mt7996_mac_init(struct mt7996_dev *dev);
+ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
+ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch
new file mode 100644
index 0000000..a6ffa60
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch
@@ -0,0 +1,146 @@
+From 52c4cb0df8974126a52d907070fcd3205eb21c28 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Fri, 6 Oct 2023 20:59:42 +0800
+Subject: [PATCH 79/98] wifi: mt76: mt7996: support backaward compatiable
+
+---
+ mmio.c | 2 +-
+ mt7996/dma.c | 2 +-
+ mt7996/main.c | 2 +-
+ mt7996/mcu.c | 2 +-
+ mt7996/mmio.c | 20 +++++++++++---------
+ mt7996/mt7996.h | 1 +
+ 6 files changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/mmio.c b/mmio.c
+index 22629af..aa6fe45 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -134,7 +134,7 @@ EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);
+ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ {
+ struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+- struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
++ struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
+ u32 length;
+ int i;
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 1163550..326fd4b 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -430,7 +430,7 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
+ irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE |
+ MT_INT_TX_DONE_BAND2;
+ mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
+- mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);
++ mtk_wed_device_start_hwrro(&mdev->mmio.wed, irq_mask, false);
+ mt7996_irq_enable(dev, irq_mask);
+
+ return 0;
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 2e0b1f1..44612e9 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1545,7 +1545,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
+ path->mtk_wdma.queue = 0;
+ path->mtk_wdma.wcid = msta->wcid.idx;
+
+- path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
++ path->mtk_wdma.amsdu_en = mtk_wed_device_support_pao(wed);
+ ctx->dev = NULL;
+
+ return 0;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 1915a22..ea52e09 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3171,7 +3171,7 @@ static int mt7996_mcu_wa_red_config(struct mt7996_dev *dev)
+
+ if (!mtk_wed_device_active(&dev->mt76.mmio.wed))
+ req.token_per_src[RED_TOKEN_SRC_CNT - 1] =
+- cpu_to_le16(MT7996_TOKEN_SIZE - MT7996_HW_TOKEN_SIZE);
++ cpu_to_le16(MT7996_SW_TOKEN_SIZE);
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET),
+ &req, sizeof(req), false);
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 38b8843..ab7e58e 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -14,7 +14,7 @@
+ #include "../trace.h"
+ #include "../dma.h"
+
+-static bool wed_enable;
++static bool wed_enable = true;
+ module_param(wed_enable, bool, 0644);
+
+ static const struct __base mt7996_reg_base[] = {
+@@ -360,14 +360,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ }
+
+ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
+- wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
++ wed->wlan.wpdma_rx[0] = wed->wlan.phy_base + hif1_ofs +
+ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
+ MT7996_RXQ_BAND0 * MT_RING_SIZE;
+
+- wed->wlan.id = 0x7991;
++ wed->wlan.chip_id = 0x7991;
+ wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
+ } else {
+- wed->wlan.hw_rro = dev->has_rro; /* default on */
++ wed->wlan.hwrro = dev->has_rro; /* default on */
+ wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
+ wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
+ wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
+@@ -375,7 +375,7 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+
+ wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
+
+- wed->wlan.wpdma_rx = wed->wlan.phy_base +
++ wed->wlan.wpdma_rx[0] = wed->wlan.phy_base +
+ MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
+ MT7996_RXQ_BAND0 * MT_RING_SIZE;
+
+@@ -417,11 +417,11 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
+ }
+
+- wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
+- wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf;
++ wed->wlan.nbuf = MT7996_TOKEN_SIZE;
++ wed->wlan.token_start = 0;
+
+- wed->wlan.amsdu_max_subframes = 8;
+- wed->wlan.amsdu_max_len = 1536;
++ wed->wlan.max_amsdu_nums = 8;
++ wed->wlan.max_amsdu_len = 1536;
+
+ wed->wlan.init_buf = mt7996_wed_init_buf;
+ wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
+@@ -442,6 +442,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ *irq = wed->irq;
+ dev->mt76.dma_dev = wed->dev;
+
++ dev->mt76.token_size = MT7996_SW_TOKEN_SIZE;
++
+ return 1;
+ #else
+ return 0;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index ba73520..55a4087 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -67,6 +67,7 @@
+ #define MT7996_EEPROM_BLOCK_SIZE 16
+ #define MT7996_TOKEN_SIZE 16384
+ #define MT7996_HW_TOKEN_SIZE 8192
++#define MT7996_SW_TOKEN_SIZE 1024
+
+ #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
+ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
index dda4d93..f1b8285 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
@@ -1,67 +1,82 @@
#patch patches (come from openwrt/lede/target/linux/mediatek)
SRC_URI_append = " \
- file://0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch \
- file://0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch \
- file://0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch \
- file://0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch \
- file://0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch \
- file://0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch \
- file://0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch \
- file://0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch \
- file://0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch \
- file://0010-wifi-mt76-mt7996-add-muru-support.patch \
- file://0011-wifi-mt76-mt7996-increase-tx-token-size.patch \
- file://0014-wifi-mt76-mt7996-set-wcid-in-txp.patch \
- file://0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch \
- file://0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
- file://0017-wifi-mt76-mt7996-add-thermal-protection-support.patch \
- file://0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
- file://0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch \
- file://0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch \
- file://0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch \
- file://0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch \
- file://0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch \
- file://0024-wifi-mt76-testmode-add-basic-testmode-support.patch \
- file://0026-wifi-mt76-mt7996-add-led-feature-support.patch \
- file://0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch \
- file://0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch \
- file://0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch \
- file://0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch \
- file://0031-wifi-mt76-mt7996-fix-memory-leak.patch \
- file://0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch \
- file://0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch \
- file://0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch \
- file://0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch \
- file://0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch \
- file://0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch \
- file://0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch \
- file://0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch \
- file://0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch \
- file://0041-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch \
+ file://0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch \
+ file://0002-wifi-mt76-wed-sync-to-wed-upstream.patch \
+ file://0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch \
+ file://0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch \
+ file://0005-wifi-mt76-mt7996-add-thermal-protection-support.patch \
+ file://0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
+ file://0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch \
+ file://0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch \
+ file://0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch \
+ file://0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch \
+ file://0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch \
+ file://0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch \
+ file://0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch \
+ file://0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch \
+ file://0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
+ file://0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch \
+ file://0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch \
+ file://0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch \
+ file://0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch \
+ file://0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch \
+ file://0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch \
+ file://0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch \
+ file://0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch \
+ file://0024-wifi-mt76-mt7996-add-kite-pci-support.patch \
+ file://0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch \
+ file://0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch \
+ file://0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch \
+ file://0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch \
+ file://0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch \
+ file://0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch \
+ file://0031-wifi-mt76-mt7996-refine-ampdu-factor.patch \
file://0999-wifi-mt76-mt7996-for-build-pass.patch \
file://1000-wifi-mt76-mt7996-add-debug-tool.patch \
- file://1001-wifi-mt76-mt7996-add-txpower-support.patch \
- file://1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch \
- file://1003-wifi-mt76-mt7996-Add-air-monitor-support.patch \
- file://1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch \
- file://1005-wifi-mt76-mt7996-add-U-NII-4-support.patch \
- file://1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch \
- file://1007-wifi-mt76-mt7996-add-binfile-mode-support.patch \
- file://1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch \
- file://1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch \
- file://1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch \
- file://1011-wifi-mt76-mt7996-add-single-sku.patch \
- file://1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch \
- file://1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch \
- file://1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch \
- file://1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch \
- file://2000-wifi-mt76-rework-wed-rx-flow.patch \
- file://2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch \
+ file://1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch \
+ file://1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch \
+ file://1003-wifi-mt76-testmode-add-basic-testmode-support.patch \
+ file://1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch \
+ file://1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch \
+ file://1006-wifi-mt76-mt7996-add-txpower-support.patch \
+ file://1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch \
+ file://1008-wifi-mt76-mt7996-Add-air-monitor-support.patch \
+ file://1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch \
+ file://1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch \
+ file://1011-wifi-mt76-mt7996-add-binfile-mode-support.patch \
+ file://1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch \
+ file://1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch \
+ file://1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch \
+ file://1015-wifi-mt76-mt7996-add-single-sku.patch \
+ file://1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch \
+ file://1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch \
+ file://1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch \
+ file://1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch \
+ file://1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch \
+ file://1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch \
+ file://1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch \
+ file://1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch \
+ file://1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch \
+ file://1025-wifi-mt76-mt7996-support-dup-wtbl.patch \
+ file://1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch \
+ file://1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch \
+ file://1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch \
+ file://1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch \
+ file://1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch \
+ file://2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch \
+ file://2001-wifi-mt76-rework-wed-rx-flow.patch \
file://2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch \
- file://2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch \
- file://2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch \
- file://2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch \
- file://2006-wifi-mt76-add-random-early-drop-support.patch \
- file://2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch \
- file://2008-wifi-mt76-add-SER-support-for-wed3.0.patch \
+ file://2003-wifi-mt76-add-random-early-drop-support.patch \
+ file://2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch \
+ file://2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch \
+ file://2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch \
+ file://2007-wifi-mt76-add-SER-support-for-wed3.0.patch \
+ file://2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch \
+ file://2009-wifi-mt76-drop-packet-based-on-ind_reason.patch \
+ file://2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch \
+ file://2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch \
+ file://2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch \
+ file://2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch \
+ file://2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch \
+ file://2999-wifi-mt76-mt7996-support-backaward-compatiable.patch \
"