[][MAC80211][misc][Add Filogic 880 Non-MLO SDK Release]

[Description]
Add Filogic 880 Non-MLO SDK Release

[Release-log]
N/A

Change-Id: I3c850bd567c34e00171fa9c99ea18bd781f7c649
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8416843
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-mtk-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
similarity index 80%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-mtk-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
index bef1050..634f7b5 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0001-mtk-Revert-wifi-mt76-mt7996-fill-txd-by-host-driver.patch
@@ -1,7 +1,8 @@
-From 455955959ceaabf80454570c2dfaa3128d524791 Mon Sep 17 00:00:00 2001
+From 79c8a28d435df3a9b0da8145675ea8d70a4de463 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"
+Subject: [PATCH 01/23] mtk: Revert "wifi: mt76: mt7996: fill txd by host
+ driver"
 
 This reverts commit 325a0c4931990d553487024c4f76c776492bdcc2.
 ---
@@ -9,10 +10,10 @@
  1 file changed, 9 insertions(+), 4 deletions(-)
 
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-index c43839a..1a1e218 100644
+index 53258488..db06a982 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,
+@@ -937,8 +937,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);
@@ -26,7 +27,7 @@
  
  	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,
+@@ -955,8 +958,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
  	}
  	txp->fw.nbuf = nbuf;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-mtk-wifi-mt76-connac-use-peer-address-for-station-BM.patch
similarity index 79%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-mtk-wifi-mt76-connac-use-peer-address-for-station-BM.patch
index 575b7db..bb26142 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-wifi-mt76-connac-use-peer-address-for-station-BMC-en.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-mtk-wifi-mt76-connac-use-peer-address-for-station-BM.patch
@@ -1,14 +1,13 @@
-From 1b0bafc1cfb554b6150eb2ea3e1a5100ef1b0a24 Mon Sep 17 00:00:00 2001
+From b7325781bb79f1ffa9d3f5a9ea9f79a59aa92e41 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
+Subject: [PATCH 02/23] mtk: 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>
 ---
@@ -17,10 +16,10 @@
  2 files changed, 11 insertions(+), 1 deletion(-)
 
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 68de525..bb570f2 100644
+index 96494ba2..0d05404f 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,
+@@ -389,7 +389,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);
@@ -37,10 +36,10 @@
  	}
  
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 832b861..0e51fe0 100644
+index 51deea84..be914ced 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -582,6 +582,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+@@ -595,6 +595,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)) {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-wifi-mt76-wed-sync-to-wed-upstream.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-wifi-mt76-wed-sync-to-wed-upstream.patch
deleted file mode 100644
index 25dfc5d..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0002-wifi-mt76-wed-sync-to-wed-upstream.patch
+++ /dev/null
@@ -1,2740 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-mtk-wifi-mt76-mt7996-disable-rx-header-translation-f.patch
similarity index 72%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-mtk-wifi-mt76-mt7996-disable-rx-header-translation-f.patch
index 1494376..955382e 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-wifi-mt76-mt7996-disable-rx-header-translation-for-B.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-mtk-wifi-mt76-mt7996-disable-rx-header-translation-f.patch
@@ -1,20 +1,19 @@
-From cb01c8f9cef451d5e478d8498902d52a92ca4b55 Mon Sep 17 00:00:00 2001
+From 70f582db962c977a71d3d618081f894c0e658046 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
+Subject: [PATCH 03/23] mtk: 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
+index 3c729b56..5a2e2d12 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,
+@@ -1769,10 +1769,10 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
  	else
  		hdr_trans->from_ds = true;
  
@@ -27,7 +26,7 @@
  	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,
+@@ -2145,6 +2145,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  	if (!enable)
  		goto out;
  
@@ -36,8 +35,8 @@
 +
  	/* 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,
+ 		/* starec hdrt mode */
+@@ -2169,8 +2172,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);
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
deleted file mode 100644
index c657c5b..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0003-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
+++ /dev/null
@@ -1,138 +0,0 @@
-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 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.
-
-Change-Id: I1312c193beab5e16aae7161a7e3bdda100b72f8d
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/eeprom.c | 21 +++++++++++++++++----
- mt7996/eeprom.h |  3 +++
- mt7996/mcu.c    |  2 +-
- mt7996/mt7996.h | 14 ++++++++++++++
- 4 files changed, 35 insertions(+), 5 deletions(-)
-
-diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 544b6c6..9db7e53 100644
---- a/mt7996/eeprom.c
-+++ b/mt7996/eeprom.c
-@@ -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)
- {
--	u8 path, nss, band_idx = phy->mt76->band_idx;
-+	u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;
- 	u8 *eeprom = dev->mt76.eeprom.data;
- 	struct mt76_phy *mphy = phy->mt76;
-+	int max_path = 5, max_nss = 4;
- 	int ret;
- 
- 	switch (band_idx) {
- 	case MT_BAND1:
- 		path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,
- 				 eeprom[MT_EE_WIFI_CONF + 2]);
-+		rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,
-+				    eeprom[MT_EE_WIFI_CONF + 3]);
- 		nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,
- 				eeprom[MT_EE_WIFI_CONF + 5]);
- 		break;
- 	case MT_BAND2:
- 		path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,
- 				 eeprom[MT_EE_WIFI_CONF + 2]);
-+		rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,
-+				    eeprom[MT_EE_WIFI_CONF + 4]);
- 		nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,
- 				eeprom[MT_EE_WIFI_CONF + 5]);
- 		break;
- 	default:
- 		path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,
- 				 eeprom[MT_EE_WIFI_CONF + 1]);
-+		rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,
-+				    eeprom[MT_EE_WIFI_CONF + 3]);
- 		nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,
- 				eeprom[MT_EE_WIFI_CONF + 4]);
- 		break;
- 	}
- 
--	if (!path || path > 4)
--		path = 4;
-+	if (!path || path > max_path)
-+		path = max_path;
- 
--	nss = min_t(u8, min_t(u8, 4, nss), path);
-+	if (!nss || nss > max_nss)
-+		nss = max_nss;
-+
-+	nss = min_t(u8, nss, path);
-+
-+	if (path != rx_path)
-+		phy->has_aux_rx = true;
- 
- 	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 0c74977..412d6e2 100644
---- a/mt7996/eeprom.h
-+++ b/mt7996/eeprom.h
-@@ -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)
-+#define MT_EE_WIFI_CONF3_RX_PATH_BAND0		GENMASK(2, 0)
-+#define MT_EE_WIFI_CONF3_RX_PATH_BAND1		GENMASK(5, 3)
-+#define MT_EE_WIFI_CONF4_RX_PATH_BAND2		GENMASK(2, 0)
- #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0	GENMASK(5, 3)
- #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 3ff70c6..328bea9 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -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),
--		.rx_path = phy->mt76->chainmask >> dev->chainshift[band_idx],
-+		.rx_path = mt7996_rx_chainmask(phy) >> dev->chainshift[band_idx],
- 		.band_idx = band_idx,
- 		.channel_band = ch_band[chandef->chan->band],
- 	};
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index c541eaa..ef84173 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -206,6 +206,8 @@ struct mt7996_phy {
- 
- 	struct mt76_mib_stats mib;
- 	struct mt76_channel_state state_ts;
-+
-+	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);
- 
-+static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
-+{
-+	int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx);
-+	int cur_nss = hweight8(phy->mt76->antenna_mask);
-+	u16 tx_chainmask = phy->mt76->chainmask;
-+
-+	if (cur_nss != max_nss)
-+		return tx_chainmask;
-+
-+	return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
-+}
-+
- 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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-mtk-wifi-mt76-check-txs-format-before-getting-skb-by.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-mtk-wifi-mt76-check-txs-format-before-getting-skb-by.patch
new file mode 100644
index 0000000..314c0b3
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-mtk-wifi-mt76-check-txs-format-before-getting-skb-by.patch
@@ -0,0 +1,57 @@
+From 87a3fa3c38e1b840cebe5f3b088a0ff67e5920f0 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Thu, 7 Dec 2023 11:17:56 +0800
+Subject: [PATCH 04/23] mtk: wifi: mt76: check txs format before getting skb by
+ pid
+
+The PPDU TxS does not include the error bit so it cannot use to report
+status to mac80211.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt76_connac3_mac.h | 5 +++++
+ mt7996/mac.c       | 6 ++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/mt76_connac3_mac.h b/mt76_connac3_mac.h
+index 83dcd964..8cfd479a 100644
+--- a/mt76_connac3_mac.h
++++ b/mt76_connac3_mac.h
+@@ -18,6 +18,11 @@ enum {
+ 	MT_LMAC_PSMP0,
+ };
+ 
++enum {
++	MT_TXS_MPDU_FMT = 0,
++	MT_TXS_PPDU_FMT = 2,
++};
++
+ #define MT_CT_PARSE_LEN			72
+ #define MT_CT_DMA_BUF_NUM		2
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index db06a982..ff7e0753 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1193,14 +1193,16 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
+ 	struct ieee80211_tx_info *info;
+ 	struct sk_buff_head list;
+ 	struct rate_info rate = {};
+-	struct sk_buff *skb;
++	struct sk_buff *skb = NULL;
+ 	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 (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_MPDU_FMT)
++		skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+ 
+ 	if (skb) {
+ 		info = IEEE80211_SKB_CB(skb);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
deleted file mode 100644
index bb8761d..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0004-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-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 04/98] wifi: mt76: mt7996: add eht mode tx stats
-
-Add eht mode bf fbk stats and bw320 through debugfs tx_stats command
-
-Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
----
- mt7996/debugfs.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 4d40ec7..9bd9535 100644
---- a/mt7996/debugfs.c
-+++ b/mt7996/debugfs.c
-@@ -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"
- 	};
- 
- 	/* 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: ");
- 
--	seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",
-+	seq_printf(s, "All: %d, EHT: %d, HE: %d, VHT: %d, HT: %d, ",
- 		   mib->tx_bf_rx_fb_all_cnt,
-+		   mib->tx_bf_rx_fb_eht_cnt,
- 		   mib->tx_bf_rx_fb_he_cnt,
- 		   mib->tx_bf_rx_fb_vht_cnt,
- 		   mib->tx_bf_rx_fb_ht_cnt);
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-mtk-wifi-mt76-mt7996-fix-some-twt-issues.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-mtk-wifi-mt76-mt7996-fix-some-twt-issues.patch
new file mode 100644
index 0000000..c2dc2f2
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-mtk-wifi-mt76-mt7996-fix-some-twt-issues.patch
@@ -0,0 +1,129 @@
+From 651d207a15f2bc281edf3c92236b88853fc41006 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Wed, 8 Nov 2023 10:17:10 +0800
+Subject: [PATCH 05/23] mtk: wifi: mt76: mt7996: fix some twt issues
+
+1. Reject twt flows with the same parameters to prevent potential issues
+causing by duplicated establishment.
+2. mt7996 can support 16 twt stations so modify the table_mask to u16.
+3. The minimum twt duration supported by mt7996 is 64 according to hardware
+design. Reply station with TWT_SETUP_CMD_DICTATE if the min_twt_dur smaller
+than 64.
+4. Fix possible unaligned pointer.
+5. Remove TWT_CONTROL_WAKE_DUR_UNIT flag because mt7996 does not support it.
+
+---
+ mt7996/mac.c    | 53 +++++++++++++++++++++++++++++++++++++++++--------
+ mt7996/mt7996.h |  3 ++-
+ 2 files changed, 47 insertions(+), 9 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index ff7e0753..e6583427 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2534,6 +2534,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
+ 	return 0;
+ }
+ 
++static bool
++mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
++			   struct ieee80211_twt_params *twt_agrt)
++{
++	u16 type = le16_to_cpu(twt_agrt->req_type);
++	u8 exp;
++	int i;
++
++	exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
++	for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
++		struct mt7996_twt_flow *f;
++
++		if (!(msta->twt.flowid_mask & BIT(i)))
++			continue;
++
++		f = &msta->twt.flow[i];
++		if (f->duration == twt_agrt->min_twt_dur &&
++		    f->mantissa == twt_agrt->mantissa &&
++		    f->exp == exp &&
++		    f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
++		    f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
++		    f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
++			return true;
++	}
++
++	return false;
++}
++
+ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ 			      struct ieee80211_sta *sta,
+ 			      struct ieee80211_twt_setup *twt)
+@@ -2545,8 +2573,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ 	enum ieee80211_twt_setup_cmd sta_setup_cmd;
+ 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ 	struct mt7996_twt_flow *flow;
+-	int flowid, table_id;
+-	u8 exp;
++	u8 flowid, table_id, exp;
+ 
+ 	if (mt7996_mac_check_twt_req(twt))
+ 		goto out;
+@@ -2559,9 +2586,19 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ 	if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
+ 		goto unlock;
+ 
++	if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
++		setup_cmd = TWT_SETUP_CMD_DICTATE;
++		twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR;
++		goto unlock;
++	}
++
++	if (mt7996_mac_twt_param_equal(msta, twt_agrt))
++		goto unlock;
++
+ 	flowid = ffs(~msta->twt.flowid_mask) - 1;
+-	le16p_replace_bits(&twt_agrt->req_type, flowid,
+-			   IEEE80211_TWT_REQTYPE_FLOWID);
++	twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
++	twt_agrt->req_type |= le16_encode_bits(flowid,
++					       IEEE80211_TWT_REQTYPE_FLOWID);
+ 
+ 	table_id = ffs(~dev->twt.table_mask) - 1;
+ 	exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
+@@ -2608,10 +2645,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ unlock:
+ 	mutex_unlock(&dev->mt76.mutex);
+ out:
+-	le16p_replace_bits(&twt_agrt->req_type, setup_cmd,
+-			   IEEE80211_TWT_REQTYPE_SETUP_CMD);
+-	twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) |
+-		       (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED);
++	twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD);
++	twt_agrt->req_type |=
++		le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD);
++	twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED;
+ }
+ 
+ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index bc73bcb4..8154ad37 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -53,6 +53,7 @@
+ 
+ #define MT7996_MAX_TWT_AGRT		16
+ #define MT7996_MAX_STA_TWT_AGRT		8
++#define MT7996_MIN_TWT_DUR		64
+ #define MT7996_MAX_QUEUE		(__MT_RXQ_MAX +	__MT_MCUQ_MAX + 3)
+ 
+ /* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+@@ -320,7 +321,7 @@ struct mt7996_dev {
+ 	struct rchan *relay_fwlog;
+ 
+ 	struct {
+-		u8 table_mask;
++		u16 table_mask;
+ 		u8 n_agrt;
+ 	} twt;
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch
deleted file mode 100644
index 9d85c7c..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0005-wifi-mt76-mt7996-add-thermal-protection-support.patch
+++ /dev/null
@@ -1,434 +0,0 @@
-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 05/98] wifi: mt76: mt7996: add thermal protection support
-
-This commit includes the following changes:
-1. implement MTK thermal protection driver API
-2. support Linux cooling device control
-
-Change-Id: I8fecc28f5b17ee50ae4644d1dd17d188dd694731
----
- mt76_connac_mcu.h |   1 +
- mt7996/init.c     | 103 +++++++++++++++++++++++++++++++++++++++++++++
- mt7996/main.c     |   8 ++++
- mt7996/mcu.c      | 105 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.h      |  44 +++++++++++++++++++
- mt7996/mt7996.h   |  15 +++++++
- 6 files changed, 276 insertions(+)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 6064973..99077f1 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -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,
- };
- 
-diff --git a/mt7996/init.c b/mt7996/init.c
-index d335b58..610d80e 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -42,6 +42,98 @@ static const struct ieee80211_iface_combination if_comb[] = {
- 	}
- };
- 
-+static int
-+mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
-+				      unsigned long *state)
-+{
-+	*state = MT7996_CDEV_THROTTLE_MAX;
-+
-+	return 0;
-+}
-+
-+static int
-+mt7996_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
-+				      unsigned long *state)
-+{
-+	struct mt7996_phy *phy = cdev->devdata;
-+
-+	*state = phy->cdev_state;
-+
-+	return 0;
-+}
-+
-+static int
-+mt7996_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
-+				      unsigned long state)
-+{
-+	struct mt7996_phy *phy = cdev->devdata;
-+	u8 throttling = MT7996_THERMAL_THROTTLE_MAX - state;
-+	int ret;
-+
-+	if (state > MT7996_CDEV_THROTTLE_MAX) {
-+		dev_err(phy->dev->mt76.dev,
-+			"please specify a valid throttling state\n");
-+		return -EINVAL;
-+	}
-+
-+	if (state == phy->cdev_state)
-+		return 0;
-+
-+	/*
-+	 * cooling_device convention: 0 = no cooling, more = more cooling
-+	 * mcu convention: 1 = max cooling, more = less cooling
-+	 */
-+	ret = mt7996_mcu_set_thermal_throttling(phy, throttling);
-+	if (ret)
-+		return ret;
-+
-+	phy->cdev_state = state;
-+
-+	return 0;
-+}
-+
-+static const struct thermal_cooling_device_ops mt7996_thermal_ops = {
-+	.get_max_state = mt7996_thermal_get_max_throttle_state,
-+	.get_cur_state = mt7996_thermal_get_cur_throttle_state,
-+	.set_cur_state = mt7996_thermal_set_cur_throttle_state,
-+};
-+
-+static void mt7996_unregister_thermal(struct mt7996_phy *phy)
-+{
-+	struct wiphy *wiphy = phy->mt76->hw->wiphy;
-+
-+	if (!phy->cdev)
-+	    return;
-+
-+	sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
-+	thermal_cooling_device_unregister(phy->cdev);
-+}
-+
-+static int mt7996_thermal_init(struct mt7996_phy *phy)
-+{
-+	struct wiphy *wiphy = phy->mt76->hw->wiphy;
-+	struct thermal_cooling_device *cdev;
-+	const char *name;
-+
-+	name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
-+			      wiphy_name(wiphy));
-+
-+	cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
-+	if (!IS_ERR(cdev)) {
-+		if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
-+				      "cooling_device") < 0)
-+			thermal_cooling_device_unregister(cdev);
-+		else
-+			phy->cdev = cdev;
-+	}
-+
-+	/* initialize critical/maximum high temperature */
-+	phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
-+	phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
-+
-+	return 0;
-+}
-+
- static void mt7996_led_set_config(struct led_classdev *led_cdev,
- 				  u8 delay_on, u8 delay_off)
- {
-@@ -419,6 +511,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
- 	if (ret)
- 		goto error;
- 
-+	ret = mt7996_thermal_init(phy);
-+	if (ret)
-+		goto error;
-+
- 	ret = mt7996_init_debugfs(phy);
- 	if (ret)
- 		goto error;
-@@ -446,6 +542,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
- 	if (!phy)
- 		return;
- 
-+	mt7996_unregister_thermal(phy);
-+
- 	mphy = phy->dev->mt76.phys[band];
- 	mt76_unregister_phy(mphy);
- 	ieee80211_free_hw(mphy->hw);
-@@ -1027,6 +1125,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
- 	if (ret)
- 		return ret;
- 
-+	ret = mt7996_thermal_init(&dev->phy);
-+	if (ret)
-+		return ret;
-+
- 	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
- 
- 	ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
-@@ -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);
-+	mt7996_unregister_thermal(&dev->phy);
- 	mt7996_coredump_unregister(dev);
- 	mt76_unregister_device(&dev->mt76);
- 	mt7996_mcu_exit(dev);
-diff --git a/mt7996/main.c b/mt7996/main.c
-index ae4f0ce..280120b 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -51,6 +51,14 @@ int mt7996_run(struct ieee80211_hw *hw)
- 	if (ret)
- 		goto out;
- 
-+	ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);
-+	if (ret)
-+		goto out;
-+
-+	ret = mt7996_mcu_set_thermal_protect(phy, true);
-+	if (ret)
-+		goto out;
-+
- 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
- 
- 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 328bea9..5310f9b 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -449,6 +449,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
- 	}
- }
- 
-+static void
-+mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
-+{
-+#define THERMAL_NOTIFY_TAG 0x4
-+#define THERMAL_NOTIFY 0x2
-+	struct mt76_phy *mphy = &dev->mt76.phy;
-+	struct mt7996_mcu_thermal_notify *n;
-+	struct mt7996_phy *phy;
-+
-+	n = (struct mt7996_mcu_thermal_notify *)skb->data;
-+
-+	if (n->tag != THERMAL_NOTIFY_TAG)
-+		return;
-+
-+	if (n->event_id != THERMAL_NOTIFY)
-+		return;
-+
-+	if (n->band_idx > MT_BAND2)
-+		return;
-+
-+	mphy = dev->mt76.phys[n->band_idx];
-+	if (!mphy)
-+		return;
-+
-+	phy = (struct mt7996_phy *)mphy->priv;
-+	phy->throttle_state = n->duty_percent;
-+}
-+
- static void
- mt7996_mcu_rx_ext_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;
-+	case MCU_UNI_EVENT_THERMAL:
-+		mt7996_mcu_rx_thermal_notify(dev, skb);
-+		break;
- 	default:
- 		break;
- 	}
-@@ -3450,6 +3481,80 @@ out:
- 	return 0;
- }
- 
-+
-+int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
-+{
-+	struct {
-+		u8 _rsv[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+
-+		struct mt7996_mcu_thermal_ctrl ctrl;
-+	} __packed req = {
-+		.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG),
-+		.len = cpu_to_le16(sizeof(req) - 4),
-+		.ctrl = {
-+			.band_idx = phy->mt76->band_idx,
-+		},
-+	};
-+	int level, ret;
-+
-+	/* set duty cycle and level */
-+	for (level = 0; level < 4; level++) {
-+		req.ctrl.duty.duty_level = level;
-+		req.ctrl.duty.duty_cycle = state;
-+		state /= 2;
-+
-+		ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
-+					&req, sizeof(req), false);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable)
-+{
-+#define SUSTAIN_PERIOD		10
-+	struct {
-+		u8 _rsv[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+
-+		struct mt7996_mcu_thermal_ctrl ctrl;
-+		struct mt7996_mcu_thermal_enable enable;
-+	} __packed req = {
-+		.len = cpu_to_le16(sizeof(req) - 4 - sizeof(req.enable)),
-+		.ctrl = {
-+			.band_idx = phy->mt76->band_idx,
-+			.type.protect_type = 1,
-+			.type.trigger_type = 1,
-+		},
-+	};
-+	int ret;
-+
-+	req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DISABLE);
-+
-+	ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
-+				&req, sizeof(req) - sizeof(req.enable), false);
-+	if (ret || !enable)
-+		return ret;
-+
-+	/* set high-temperature trigger threshold */
-+	req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_ENABLE);
-+	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);
-+
-+	req.len = cpu_to_le16(sizeof(req) - 4);
-+
-+	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
-+				 &req, sizeof(req), false);
-+}
-+
- int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
- {
- 	struct {
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index e4b3122..f1528df 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
- 	__le32 status; /* 0: success, others: fail */
- } __packed;
- 
-+struct mt7996_mcu_thermal_ctrl {
-+	u8 ctrl_id;
-+	u8 band_idx;
-+	union {
-+		struct {
-+			u8 protect_type; /* 1: duty admit, 2: radio off */
-+			u8 trigger_type; /* 0: low, 1: high */
-+		} __packed type;
-+		struct {
-+			u8 duty_level;	/* level 0~3 */
-+			u8 duty_cycle;
-+		} __packed duty;
-+	};
-+} __packed;
-+
-+struct mt7996_mcu_thermal_enable {
-+	__le32 trigger_temp;
-+	__le32 restore_temp;
-+	__le16 sustain_time;
-+	u8 rsv[2];
-+} __packed;
-+
- struct mt7996_mcu_csa_notify {
- 	struct mt7996_mcu_rxd rxd;
- 
-@@ -153,6 +175,22 @@ struct mt7996_mcu_mib {
- 	__le64 data;
- } __packed;
- 
-+struct mt7996_mcu_thermal_notify {
-+	struct mt7996_mcu_rxd rxd;
-+
-+	u8 __rsv1[4];
-+
-+	__le16 tag;
-+	__le16 len;
-+
-+	u8 event_id;
-+	u8 band_idx;
-+	u8 level_idx;
-+	u8 duty_percent;
-+	__le32 restore_temp;
-+	u8 __rsv2[4];
-+} __packed;
-+
- enum mt7996_chan_mib_offs {
- 	UNI_MIB_OBSS_AIRTIME = 26,
- 	UNI_MIB_NON_WIFI_TIME = 27,
-@@ -656,6 +694,12 @@ enum{
- 	UNI_CMD_SR_SET_SIGA = 0xd0,
- };
- 
-+enum {
-+	UNI_CMD_THERMAL_PROTECT_ENABLE = 0x6,
-+	UNI_CMD_THERMAL_PROTECT_DISABLE,
-+	UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
-+};
-+
- enum {
- 	UNI_CMD_ACCESS_REG_BASIC = 0x0,
- 	UNI_CMD_ACCESS_RF_REG_BASIC,
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index ef84173..e1972e9 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -50,6 +50,13 @@
- #define MT7996_BASIC_RATES_TBL		11
- #define MT7996_BEACON_RATES_TBL		25
- 
-+#define MT7996_THERMAL_THROTTLE_MAX	100
-+#define MT7996_CDEV_THROTTLE_MAX	99
-+#define MT7996_CRIT_TEMP_IDX		0
-+#define MT7996_MAX_TEMP_IDX		1
-+#define MT7996_CRIT_TEMP		110
-+#define MT7996_MAX_TEMP			120
-+
- #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;
- 
-+	struct thermal_cooling_device *cdev;
-+	u8 cdev_state;
-+	u8 throttle_state;
-+	u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
-+
- 	u32 rxfilter;
- 	u64 omac_mask;
- 
-@@ -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, 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,
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-mtk-wifi-mt76-mt7996-disable-AMSDU-for-non-data-fram.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-mtk-wifi-mt76-mt7996-disable-AMSDU-for-non-data-fram.patch
new file mode 100644
index 0000000..6b813fd
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-mtk-wifi-mt76-mt7996-disable-AMSDU-for-non-data-fram.patch
@@ -0,0 +1,39 @@
+From abd4da501a5b6d4159f8ef3dbcfc9f646ecc8a40 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 6 Nov 2023 20:17:16 +0800
+Subject: [PATCH 06/23] mtk: wifi: mt76: mt7996: disable AMSDU for non-data
+ frames
+
+Mgmt. frames with amsdu may lead to unexpected errors.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mac.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index e6583427..19b34066 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -732,6 +732,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
+ 	      FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
+ 
+ 	txwi[2] |= cpu_to_le32(val);
++
++	if (wcid->amsdu)
++		txwi[3] |= cpu_to_le32(MT_TXD3_HW_AMSDU);
+ }
+ 
+ static void
+@@ -862,8 +865,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ 		val |= MT_TXD3_PROTECT_FRAME;
+ 	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ 		val |= MT_TXD3_NO_ACK;
+-	if (wcid->amsdu)
+-		val |= MT_TXD3_HW_AMSDU;
+ 
+ 	txwi[3] = cpu_to_le32(val);
+ 	txwi[4] = 0;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
deleted file mode 100644
index a4338f3..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0006-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
+++ /dev/null
@@ -1,185 +0,0 @@
-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 06/98] wifi: mt76: mt7996: add thermal sensor device support
-
----
- mt7996/init.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.c  | 41 ++++++++++++++++++++++++
- 2 files changed, 129 insertions(+)
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 610d80e..de4a5f7 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -4,6 +4,8 @@
-  */
- 
- #include <linux/etherdevice.h>
-+#include <linux/hwmon.h>
-+#include <linux/hwmon-sysfs.h>
- #include <linux/thermal.h>
- #include "mt7996.h"
- #include "mac.h"
-@@ -42,6 +44,82 @@ static const struct ieee80211_iface_combination if_comb[] = {
- 	}
- };
- 
-+static ssize_t mt7996_thermal_temp_show(struct device *dev,
-+					struct device_attribute *attr,
-+					char *buf)
-+{
-+	struct mt7996_phy *phy = dev_get_drvdata(dev);
-+	int i = to_sensor_dev_attr(attr)->index;
-+	int temperature;
-+
-+	switch (i) {
-+	case 0:
-+		temperature = mt7996_mcu_get_temperature(phy);
-+		if (temperature < 0)
-+			return temperature;
-+		/* display in millidegree celcius */
-+		return sprintf(buf, "%u\n", temperature * 1000);
-+	case 1:
-+	case 2:
-+		return sprintf(buf, "%u\n",
-+			       phy->throttle_temp[i - 1] * 1000);
-+	case 3:
-+		return sprintf(buf, "%hhu\n", phy->throttle_state);
-+	default:
-+		return -EINVAL;
-+	}
-+}
-+
-+static ssize_t mt7996_thermal_temp_store(struct device *dev,
-+					 struct device_attribute *attr,
-+					 const char *buf, size_t count)
-+{
-+	struct mt7996_phy *phy = dev_get_drvdata(dev);
-+	int ret, i = to_sensor_dev_attr(attr)->index;
-+	long val;
-+
-+	ret = kstrtol(buf, 10, &val);
-+	if (ret < 0)
-+		return ret;
-+
-+	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] - 10) ||
-+	    (i - 1 == MT7996_MAX_TEMP_IDX &&
-+	     val - 10 < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
-+		dev_err(phy->dev->mt76.dev,
-+			"temp1_max shall be 10 degrees higher than temp1_crit.");
-+		mutex_unlock(&phy->dev->mt76.mutex);
-+		return -EINVAL;
-+	}
-+
-+	phy->throttle_temp[i - 1] = val;
-+	mutex_unlock(&phy->dev->mt76.mutex);
-+
-+	ret = mt7996_mcu_set_thermal_protect(phy, true);
-+	if (ret)
-+		return ret;
-+
-+	return count;
-+}
-+
-+static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7996_thermal_temp, 0);
-+static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7996_thermal_temp, 1);
-+static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7996_thermal_temp, 2);
-+static SENSOR_DEVICE_ATTR_RO(throttle1, mt7996_thermal_temp, 3);
-+
-+static struct attribute *mt7996_hwmon_attrs[] = {
-+	&sensor_dev_attr_temp1_input.dev_attr.attr,
-+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
-+	&sensor_dev_attr_temp1_max.dev_attr.attr,
-+	&sensor_dev_attr_throttle1.dev_attr.attr,
-+	NULL,
-+};
-+ATTRIBUTE_GROUPS(mt7996_hwmon);
-+
- static int
- mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
- 				      unsigned long *state)
-@@ -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;
-+	struct device *hwmon;
- 	const char *name;
- 
- 	name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
-@@ -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;
- 
-+	if (!IS_REACHABLE(CONFIG_HWMON))
-+		return 0;
-+
-+	hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
-+						       mt7996_hwmon_groups);
-+
-+	if (IS_ERR(hwmon))
-+		return PTR_ERR(hwmon);
-+
- 	return 0;
- }
- 
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 5310f9b..8320c8c 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -3481,6 +3481,47 @@ out:
- 	return 0;
- }
- 
-+int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
-+{
-+#define TEMPERATURE_QUERY 0
-+#define GET_TEMPERATURE 0
-+	struct {
-+		u8 _rsv[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+
-+		u8 rsv1;
-+		u8 action;
-+		u8 band_idx;
-+		u8 rsv2;
-+	} req = {
-+		.tag = cpu_to_le16(TEMPERATURE_QUERY),
-+		.len = cpu_to_le16(sizeof(req) - 4),
-+		.action = GET_TEMPERATURE,
-+		.band_idx = phy->mt76->band_idx,
-+	};
-+	struct mt7996_mcu_thermal {
-+		u8 _rsv[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+
-+		__le32 rsv;
-+		__le32 temperature;
-+	} __packed *res;
-+	struct sk_buff *skb;
-+	int ret;
-+
-+	ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
-+					&req, sizeof(req), true, &skb);
-+	if (ret)
-+		return ret;
-+
-+	res = (void *)skb->data;
-+
-+	return le32_to_cpu(res->temperature);
-+}
- 
- int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
- {
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-mtk-wifi-mt76-mt7996-fix-incorrect-interpretation-of.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-mtk-wifi-mt76-mt7996-fix-incorrect-interpretation-of.patch
new file mode 100644
index 0000000..36cd7ee
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-mtk-wifi-mt76-mt7996-fix-incorrect-interpretation-of.patch
@@ -0,0 +1,72 @@
+From 27ad6ee9498d3293dca55d04af1fba221460d74c Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Mon, 4 Dec 2023 15:39:00 +0800
+Subject: [PATCH 07/23] mtk: wifi: mt76: mt7996: fix incorrect interpretation
+ of EHT MCS and NSS capabilities
+
+The EHT-MCS Map (20 MHz-Only Non-AP STA) subfield of the Supported EHT-MCS And NSS Set field in the EHT Capabilities element is not present for AP. Therefore, STA should not parse the subfield.
+Moreover, AP should parse the subfield only if STA is 20 MHz-Only, which is confirmed by checking the Supported Channel Width Set subfield in the HE Capabilities element.
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt7996/mcu.c | 33 +++++++++++++++++++++++++++++----
+ 1 file changed, 29 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 5a2e2d12..8c033030 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1237,9 +1237,32 @@ mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ 	he_6g->capa = sta->deflink.he_6ghz_capa.capa;
+ }
+ 
++static bool
++mt7996_mcu_sta_only_20mhz(struct ieee80211_sta *sta)
++{
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++	u8 bw = sta->deflink.he_cap.he_cap_elem.phy_cap_info[0];
++	u8 band_idx = msta->vif->mt76.band_idx;
++
++	if (band_idx == MT_BAND0) {
++		if (!(bw & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G))
++			return true;
++	} else {
++		if (!(bw & (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
++		            IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
++		            IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)))
++			return true;
++	}
++
++	return false;
++}
++
+ static void
+ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ {
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++	struct ieee80211_vif *vif = container_of((void *)msta->vif,
++	                                         struct ieee80211_vif, drv_priv);
+ 	struct ieee80211_eht_mcs_nss_supp *mcs_map;
+ 	struct ieee80211_eht_cap_elem_fixed *elem;
+ 	struct sta_rec_eht *eht;
+@@ -1259,11 +1282,13 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ 	eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info);
+ 	eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]);
+ 
+-	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
++	if (vif->type != NL80211_IFTYPE_STATION && mt7996_mcu_sta_only_20mhz(sta))
+ 		memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20));
+-	memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
+-	memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
+-	memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
++	else {
++		memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
++		memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
++		memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
++	}
+ }
+ 
+ static void
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
deleted file mode 100644
index 873029f..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0007-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
+++ /dev/null
@@ -1,211 +0,0 @@
-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 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.
-
-Change-Id: Ifcb49504f02f5cc6a23c626e30b4f0e1360fe157
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- mt7996/dma.c    | 14 +++++++-------
- mt7996/init.c   | 29 ++++++++++++++++++-----------
- mt7996/mcu.c    | 13 +++++--------
- mt7996/mt7996.h | 11 +++++++++++
- mt7996/regs.h   |  3 +++
- 5 files changed, 44 insertions(+), 26 deletions(-)
-
-diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 2221d22..3d04470 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -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))
- 		irq_mask |= MT_INT_BAND0_RX_DONE;
- 
--	if (dev->dbdc_support)
-+	if (mt7996_band_valid(dev, MT_BAND1))
- 		irq_mask |= MT_INT_BAND1_RX_DONE;
- 
--	if (dev->tbtc_support)
-+	if (mt7996_band_valid(dev, MT_BAND2))
- 		irq_mask |= MT_INT_BAND2_RX_DONE;
- 
- 	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],
-@@ -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 de4a5f7..2e6efc5 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -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;
--
--	if ((band == MT_BAND1 && !dev->dbdc_support) ||
--	    (band == MT_BAND2 && !dev->tbtc_support))
-+	if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
- 		return 0;
- 
- 	if (phy)
-@@ -782,8 +778,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
- 
- 	INIT_WORK(&dev->init_work, mt7996_init_work);
- 
--	dev->dbdc_support = true;
--	dev->tbtc_support = true;
-+	dev->dbdc_support = mt7996_band_valid(dev, MT_BAND1) ||
-+			    mt7996_band_valid(dev, MT_BAND2);
-+	dev->tbtc_support = mt7996_band_valid(dev, MT_BAND1) &&
-+			    mt7996_band_valid(dev, MT_BAND2);
- 
- 	ret = mt7996_dma_init(dev);
- 	if (ret)
-@@ -1217,8 +1215,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
- 	if (ret)
- 		return ret;
- 
--	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
--
- 	ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
- 	if (ret)
- 		return ret;
-@@ -1227,13 +1223,24 @@ int mt7996_register_device(struct mt7996_dev *dev)
- 	if (ret)
- 		return ret;
- 
-+	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
-+
- 	dev->recovery.hw_init_done = true;
- 
- 	ret = mt7996_init_debugfs(&dev->phy);
- 	if (ret)
--		return ret;
-+		goto error;
- 
--	return mt7996_coredump_register(dev);
-+	ret = mt7996_coredump_register(dev);
-+	if (ret)
-+		goto error;
-+
-+	return 0;
-+
-+error:
-+	cancel_work_sync(&dev->init_work);
-+
-+	return ret;
- }
- 
- void mt7996_unregister_device(struct mt7996_dev *dev)
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-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)
- {
- 	struct uni_header hdr = {};
- 	struct sk_buff *skb;
--	int len, num;
-+	int len, num, i;
- 
- 	num = 2 + 2 * (dev->dbdc_support + dev->tbtc_support);
- 	len = sizeof(hdr) + num * sizeof(struct vow_rx_airtime);
-@@ -2777,13 +2777,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
- 
- 	skb_put_data(skb, &hdr, sizeof(hdr));
- 
--	mt7996_add_rx_airtime_tlv(skb, dev->mt76.phy.band_idx);
--
--	if (dev->dbdc_support)
--		mt7996_add_rx_airtime_tlv(skb, MT_BAND1);
--
--	if (dev->tbtc_support)
--		mt7996_add_rx_airtime_tlv(skb, MT_BAND2);
-+	for (i = 0; i < __MT_MAX_BAND; i++) {
-+		if (mt7996_band_valid(dev, i))
-+			mt7996_add_rx_airtime_tlv(skb, i);
-+	}
- 
- 	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 e1972e9..137d5a2 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -381,6 +381,17 @@ mt7996_phy3(struct mt7996_dev *dev)
- 	return __mt7996_phy(dev, MT_BAND2);
- }
- 
-+static inline bool
-+mt7996_band_valid(struct mt7996_dev *dev, u8 band)
-+{
-+	/* tri-band support */
-+	if (band <= MT_BAND2 &&
-+	    mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
-+		return true;
-+
-+	return band == MT_BAND0 || band == MT_BAND2;
-+}
-+
- extern const struct ieee80211_ops mt7996_ops;
- 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 854390d..a4d5ad8 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -602,6 +602,9 @@ enum base_rev {
- #define MT_TOP_MISC				MT_TOP(0xf0)
- #define MT_TOP_MISC_FW_STATE			GENMASK(2, 0)
- 
-+#define MT_PAD_GPIO				0x700056f0
-+#define MT_PAD_GPIO_ADIE_COMB			GENMASK(16, 15)
-+
- #define MT_HW_REV				0x70010204
- #define MT_WF_SUBSYS_RST			0x70028600
- 
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-mtk-wifi-mt76-mt7992-add-TLV-sanity-check.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-mtk-wifi-mt76-mt7992-add-TLV-sanity-check.patch
new file mode 100644
index 0000000..110888b
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-mtk-wifi-mt76-mt7992-add-TLV-sanity-check.patch
@@ -0,0 +1,74 @@
+From 6bef1f8c48baa71a2c7b4bc22e30915fe0651b92 Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Thu, 9 Nov 2023 10:35:13 +0800
+Subject: [PATCH 08/23] mtk: wifi: mt76: mt7992: add TLV sanity check
+
+If TLV involves beacon content, its length might not be 4-byte aligned.
+Therefore, 4-byte alignment check and padding, if necessary, are performed before sending TLV to FW.
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt7996/mcu.c | 14 +++++---------
+ mt7996/mcu.h |  4 ++--
+ 2 files changed, 7 insertions(+), 11 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 8c033030..071a9ec2 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -732,13 +732,10 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ static struct tlv *
+ mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len)
+ {
+-	struct tlv *ptlv, tlv = {
+-		.tag = cpu_to_le16(tag),
+-		.len = cpu_to_le16(len),
+-	};
++	struct tlv *ptlv = skb_put(skb, len);
+ 
+-	ptlv = skb_put(skb, len);
+-	memcpy(ptlv, &tlv, sizeof(tlv));
++	ptlv->tag = cpu_to_le16(tag);
++	ptlv->len = cpu_to_le16(len);
+ 
+ 	return ptlv;
+ }
+@@ -2536,7 +2533,7 @@ 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;
++	len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + skb->len, 4);
+ 	tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
+ 	bcn = (struct bss_bcn_content_tlv *)tlv;
+ 	bcn->enable = en;
+@@ -2605,8 +2602,7 @@ 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);
+ 
+-	len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
+-
++	len = ALIGN(sizeof(*discov) + MT_TXD_SIZE + skb->len, 4);
+ 	tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
+ 
+ 	discov = (struct bss_inband_discovery_tlv *)tlv;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 3e013b20..a9ba63d1 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -800,10 +800,10 @@ enum {
+ 					 sizeof(struct sta_rec_hdr_trans) +	\
+ 					 sizeof(struct tlv))
+ 
+-#define MT7996_MAX_BEACON_SIZE		1342
++#define MT7996_MAX_BEACON_SIZE		1338
+ #define MT7996_BEACON_UPDATE_SIZE	(sizeof(struct bss_req_hdr) +		\
+ 					 sizeof(struct bss_bcn_content_tlv) +	\
+-					 MT_TXD_SIZE +				\
++					 4 + MT_TXD_SIZE +			\
+ 					 sizeof(struct bss_bcn_cntdwn_tlv) +	\
+ 					 sizeof(struct bss_bcn_mbss_tlv))
+ #define MT7996_MAX_BSS_OFFLOAD_SIZE	(MT7996_MAX_BEACON_SIZE +		\
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
deleted file mode 100644
index a5b808a..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0008-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
+++ /dev/null
@@ -1,237 +0,0 @@
-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 08/98] wifi: mt76: mt7996: add beacon duplicate tx mode
- support
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- mt76_connac_mcu.h |  1 +
- mt7996/init.c     |  6 ++++--
- mt7996/mac.c      | 11 -----------
- mt7996/main.c     | 18 +++++++++---------
- mt7996/mcu.c      | 30 ++++++++++++++++++++++++++++++
- mt7996/mcu.h      | 20 ++++++++++++++++++++
- mt7996/mt7996.h   |  8 +++++---
- 7 files changed, 69 insertions(+), 25 deletions(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 99077f1..90c08d2 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -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_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 2e6efc5..17a4abd 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -354,6 +354,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
- 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
- 
- 	phy->slottime = 9;
-+	phy->beacon_rate = -1;
- 
- 	hw->sta_data_size = sizeof(struct mt7996_sta);
- 	hw->vif_data_size = sizeof(struct mt7996_vif);
-@@ -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;
--		u16 idx = MT7996_BASIC_RATES_TBL + i;
-+		/* odd index for driver, even index for firmware */
-+		u16 idx = MT7996_BASIC_RATES_TBL + 2 * i;
- 
- 		rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
- 		       FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
--		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
-+		mt7996_mcu_set_fixed_rate_table(&dev->phy, idx, rate, false);
- 	}
- }
- 
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 4be5410..6688186 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -248,17 +248,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
- 		mt76_clear(dev, addr, BIT(5));
- }
- 
--void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
--				     u8 tbl_idx, u16 rate_idx)
--{
--	u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
--
--	mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
--	/* use wtbl spe idx */
--	mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
--	mt76_wr(dev, MT_WTBL_ITCR, ctrl);
--}
--
- /* 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 280120b..41f0fa1 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -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;
-+	u8 i, idx;
- 
- 	rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
--	ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
- 
--	if (beacon && ht) {
--		struct mt7996_dev *dev = mt7996_hw_dev(hw);
-+	if (beacon) {
-+		struct mt7996_phy *phy = mt7996_hw_phy(hw);
-+
-+		/* odd index for driver, even index for firmware */
-+		idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
-+		if (phy->beacon_rate != rate)
-+			mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);
- 
--		/* must odd index */
--		idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
--		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
- 		return idx;
- 	}
- 
- 	idx = FIELD_GET(MT_TX_RATE_IDX, rate);
- 	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
- 		if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
--			return MT7996_BASIC_RATES_TBL + i;
-+			return MT7996_BASIC_RATES_TBL + 2 * i;
- 
- 	return mvif->basic_rates_idx;
- }
-@@ -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);
- 
--	/* TODO: update bmc_wtbl spe_idx when antenna changes */
- 	mutex_unlock(&dev->mt76.mutex);
- 
- 	return 0;
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 84f362b..dbb3ceb 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -4055,6 +4055,36 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
- 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
- }
- 
-+int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
-+				    u16 rate_idx, bool beacon)
-+{
-+#define UNI_FIXED_RATE_TABLE_SET	0
-+#define SPE_IXD_SELECT_TXD		0
-+#define SPE_IXD_SELECT_BMC_WTBL		1
-+	struct mt7996_dev *dev = phy->dev;
-+	struct fixed_rate_table_ctrl req = {
-+		.tag = cpu_to_le16(UNI_FIXED_RATE_TABLE_SET),
-+		.len = cpu_to_le16(sizeof(req) - 4),
-+		.table_idx = table_idx,
-+		.rate_idx = cpu_to_le16(rate_idx),
-+		.gi = 1,
-+		.he_ltf = 1,
-+	};
-+	u8 band_idx = phy->mt76->band_idx;
-+
-+	if (beacon) {
-+		req.spe_idx_sel = SPE_IXD_SELECT_TXD;
-+		req.spe_idx = 24 + band_idx;
-+		phy->beacon_rate = rate_idx;
-+	} else {
-+		req.spe_idx_sel = SPE_IXD_SELECT_BMC_WTBL;
-+		req.spe_idx = 0;
-+	}
-+
-+	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(FIXED_RATE_TABLE),
-+				 &req, sizeof(req), false);
-+}
-+
- int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
- {
- 	struct {
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index f1528df..c20a947 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -738,4 +738,24 @@ enum {
- #define MT7996_SEC_KEY_IDX		GENMASK(2, 1)
- #define MT7996_SEC_IV			BIT(3)
- 
-+struct fixed_rate_table_ctrl {
-+	u8 _rsv[4];
-+
-+	__le16 tag;
-+	__le16 len;
-+
-+	u8 table_idx;
-+	u8 antenna_idx;
-+	__le16 rate_idx;
-+	u8 spe_idx_sel;
-+	u8 spe_idx;
-+	u8 gi;
-+	u8 he_ltf;
-+	bool ldpc;
-+	bool txbf;
-+	bool dynamic_bw;
-+
-+	u8 rsv[1];
-+} __packed;
-+
- #endif
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 137d5a2..21ad51d 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -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 */
--#define MT7996_BASIC_RATES_TBL		11
-+#define MT7996_BASIC_RATES_TBL		31
- #define MT7996_BEACON_RATES_TBL		25
- 
- #define MT7996_THERMAL_THROTTLE_MAX	100
-@@ -213,6 +213,8 @@ struct mt7996_phy {
- 
- 	u8 rdd_state;
- 
-+	u16 beacon_rate;
-+
- 	u32 rx_ampdu_ts;
- 	u32 ampdu_ref;
- 
-@@ -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);
-+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);
-@@ -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);
--void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
--				     u8 tbl_idx, u16 rate_idx);
- 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,
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-mtk-wifi-mt76-mt7996-fix-HE-beamformer-phy-cap-for-s.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-mtk-wifi-mt76-mt7996-fix-HE-beamformer-phy-cap-for-s.patch
new file mode 100644
index 0000000..8f6f7ad
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-mtk-wifi-mt76-mt7996-fix-HE-beamformer-phy-cap-for-s.patch
@@ -0,0 +1,36 @@
+From cf403f86913aa78ea951d0dc11b89409f257c01b Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 23 Nov 2023 20:06:26 +0800
+Subject: [PATCH 09/23] mtk: wifi: mt76: mt7996: fix HE beamformer phy cap for
+ station vif
+
+Without this commit, station mode will not set all needed bit in HE Phy
+capabilities IE as 1.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/init.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 1a9aa48c..50dcce9f 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -1011,11 +1011,12 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
+ 	/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
+ 	elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;
+ 
+-	if (vif != NL80211_IFTYPE_AP)
++	if (!(vif == NL80211_IFTYPE_AP || vif == NL80211_IFTYPE_STATION))
+ 		return;
+ 
+ 	elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
+-	elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
++	if (vif == NL80211_IFTYPE_AP)
++		elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+ 
+ 	c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
+ 		       sts - 1) |
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
deleted file mode 100644
index b151c94..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0009-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-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 09/98] wifi: mt76: mt7996: fix bss rate tlv to sync firmware
- change
-
-Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
----
- mt7996/mcu.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index c20a947..78ecd75 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -259,7 +259,7 @@ struct bss_rate_tlv {
- 	u8 short_preamble;
- 	u8 bc_fixed_rate;
- 	u8 mc_fixed_rate;
--	u8 __rsv2[1];
-+	u8 __rsv2[9];
- } __packed;
- 
- struct bss_ra_tlv {
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-mtk-wifi-mt76-mt7996-Let-MAC80211-handles-GCMP-IGTK.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-mtk-wifi-mt76-mt7996-Let-MAC80211-handles-GCMP-IGTK.patch
new file mode 100644
index 0000000..96ee97d
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-mtk-wifi-mt76-mt7996-Let-MAC80211-handles-GCMP-IGTK.patch
@@ -0,0 +1,34 @@
+From e154e95bd733a456c5551ae89ef5673d57941b2a Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Fri, 8 Dec 2023 16:23:37 +0800
+Subject: [PATCH 10/23] mtk: wifi: mt76: mt7996: Let MAC80211 handles GCMP IGTK
+
+Because the FW does not support IGTK in GCMP mode, mt76 returns "not
+support" to mac80211, and mac80211 will handle the integrity calculation
+and validation.
+
+---
+ mt7996/main.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index be914ced..6e88420e 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -350,9 +350,12 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 	case WLAN_CIPHER_SUITE_GCMP:
+ 	case WLAN_CIPHER_SUITE_GCMP_256:
+ 	case WLAN_CIPHER_SUITE_SMS4:
++		break;
+ 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+-		break;
++		if (key->keyidx == 6 || key->keyidx == 7)
++			break;
++		fallthrough;
+ 	case WLAN_CIPHER_SUITE_WEP40:
+ 	case WLAN_CIPHER_SUITE_WEP104:
+ 	default:
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
deleted file mode 100644
index ca966b6..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0010-wifi-mt76-mt7996-adjust-wfdma-setting-to-enhance-thr.patch
+++ /dev/null
@@ -1,157 +0,0 @@
-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 10/98] wifi: mt76: mt7996: adjust wfdma setting to enhance
- throughput
-
-1. Set band 1 traffic to pcie1.
-2. Refactor dma prefetch and enlarge txd prefetch size.
-3. Update pdma setting.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- 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 3d04470..1ed91da 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -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);
- }
- 
-+static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth)
-+{
-+	u32 ret = *base << 16 | depth;
-+
-+	*base = *base + (depth << 4);
-+
-+	return ret;
-+}
-+
- static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
- {
--#define PREFETCH(_base, _depth)	((_base) << 16 | (_depth))
-+	u16 base = 0;
-+
-+#define PREFETCH(_depth)	(__mt7996_dma_prefetch_base(&base, (_depth)))
- 	/* prefetch SRAM wrapping boundary for tx/rx ring. */
--	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x0, 0x2));
--	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x20, 0x2));
--	mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x40, 0x4));
--	mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x80, 0x4));
--	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0xc0, 0x2));
--	mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0xe0, 0x4));
--	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x120, 0x2));
--	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x140, 0x2));
--	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x160, 0x2));
--	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x180, 0x2));
--	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));
-+	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x2));
-+	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x2));
-+	mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x8));
-+	mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8));
-+	mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x2));
-+	mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8));
-+	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));
-+	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->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);
- 
-+	/* WFDMA rx threshold */
-+	mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH, 0xc000c);
-+	mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH, 0x10008);
-+	mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_89_TH, 0x10008);
-+	mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_RRO_TH, 0x20);
-+
- 	if (dev->hif2) {
- 		/* GLO_CFG_EXT0 */
- 		mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
-@@ -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,
--			 MT_WFDMA_HOST_CONFIG_PDMA_BAND);
-+			 MT_WFDMA_HOST_CONFIG_PDMA_BAND |
-+			 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
-+
-+		/* AXI read outstanding number */
-+		mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
-+			 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
-+
-+		/* WFDMA rx threshold */
-+		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH + hif1_ofs, 0xc000c);
-+		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH + hif1_ofs, 0x10008);
-+		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_89_TH + hif1_ofs, 0x10008);
-+		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_RRO_TH + hif1_ofs, 0x20);
- 	}
- 
- 	if (dev->hif2) {
-diff --git a/mt7996/regs.h b/mt7996/regs.h
-index a4d5ad8..f7c99cd 100644
---- a/mt7996/regs.h
-+++ b/mt7996/regs.h
-@@ -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)
- 
-+#define MT_WFDMA0_PAUSE_RX_Q_45_TH		MT_WFDMA0(0x268)
-+#define MT_WFDMA0_PAUSE_RX_Q_67_TH		MT_WFDMA0(0x26c)
-+#define MT_WFDMA0_PAUSE_RX_Q_89_TH		MT_WFDMA0(0x270)
-+#define MT_WFDMA0_PAUSE_RX_Q_RRO_TH		MT_WFDMA0(0x27c)
-+
- #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)
-@@ -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)
-+#define MT_WFDMA_HOST_CONFIG_BAND2_PCIE1	BIT(22)
- 
- #define MT_WFDMA_EXT_CSR_HIF_MISC		MT_WFDMA_EXT_CSR(0x44)
- #define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY		BIT(0)
- 
-+#define MT_WFDMA_AXI_R2A_CTRL			MT_WFDMA_EXT_CSR(0x500)
-+#define MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK	GENMASK(4, 0)
-+
- #define MT_PCIE_RECOG_ID			0xd7090
- #define MT_PCIE_RECOG_ID_MASK			GENMASK(30, 0)
- #define MT_PCIE_RECOG_ID_SEM			BIT(31)
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-mtk-wifi-mt76-mt7996-fix-efuse-read-issue.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-mtk-wifi-mt76-mt7996-fix-efuse-read-issue.patch
new file mode 100644
index 0000000..b24231f
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-mtk-wifi-mt76-mt7996-fix-efuse-read-issue.patch
@@ -0,0 +1,30 @@
+From 68cbc6f4aa32410876f18d54f053b4f928b4b981 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 29 Nov 2023 10:55:15 +0800
+Subject: [PATCH 11/23] mtk: wifi: mt76: mt7996: fix efuse read issue
+
+The efuse data starts at 48 bytes instead of 64 bytes in the returned
+skb.
+This patch should be upstreamed.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mcu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 071a9ec2..98ea9c20 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3561,7 +3561,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
+ 		u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
+ 		u8 *buf = (u8 *)dev->mt76.eeprom.data + addr;
+ 
+-		skb_pull(skb, 64);
++		skb_pull(skb, 48);
+ 		memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
+ 	}
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch
deleted file mode 100644
index d32dea5..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0011-wifi-mt76-mt7996-fill-txd-bandwidth-filed-value-for-.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-mtk-wifi-mt76-mt7996-enable-ser-query.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-mtk-wifi-mt76-mt7996-enable-ser-query.patch
new file mode 100644
index 0000000..2ca9151
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-mtk-wifi-mt76-mt7996-enable-ser-query.patch
@@ -0,0 +1,29 @@
+From ca4d4dc688f96320065b35c9b473e378dddef56b Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 30 Oct 2023 20:19:41 +0800
+Subject: [PATCH 12/23] mtk: wifi: mt76: mt7996: enable ser query
+
+Do not return -EINVAL when action is UNI_CMD_SER_QUERY for user
+to dump SER information from FW.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mcu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 98ea9c20..8c756b31 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3852,6 +3852,8 @@ int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
+ 	};
+ 
+ 	switch (action) {
++	case UNI_CMD_SER_QUERY:
++		break;
+ 	case UNI_CMD_SER_SET:
+ 		req.set.mask = cpu_to_le32(val);
+ 		break;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch
deleted file mode 100644
index 3a49f34..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0012-wifi-mt76-mt7996-add-IEEE80211_RC_SMPS_CHANGED-handl.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-mtk-wifi-mt76-mt7996-init-rcpi-to-use-better-init-mc.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-mtk-wifi-mt76-mt7996-init-rcpi-to-use-better-init-mc.patch
new file mode 100644
index 0000000..8eded5f
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-mtk-wifi-mt76-mt7996-init-rcpi-to-use-better-init-mc.patch
@@ -0,0 +1,35 @@
+From c59e5d1ee99fbe46418efb2eacb6755db54b8e57 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Nov 2023 20:15:39 +0800
+Subject: [PATCH 13/23] mtk: wifi: mt76: mt7996: init rcpi to use better init
+ mcs
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mcu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 8c756b31..48a1e822 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1981,6 +1981,7 @@ static void
+ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
+ 			     struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+ {
++#define INIT_RCPI 180
+ 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ 	struct mt76_phy *mphy = mvif->phy->mt76;
+ 	struct cfg80211_chan_def *chandef = &mphy->chandef;
+@@ -2078,6 +2079,8 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
+ 					       IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
+ 	}
+ 	ra->sta_cap = cpu_to_le32(cap);
++
++	memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
+ }
+ 
+ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch
deleted file mode 100644
index 5f85886..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0013-wifi-mt76-mt7996-fix-mcu-command-format-to-align-fir.patch
+++ /dev/null
@@ -1,154 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-mtk-wifi-mt76-mt7996-Fix-TGax-HE-4.51.1_24G-fail.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-mtk-wifi-mt76-mt7996-Fix-TGax-HE-4.51.1_24G-fail.patch
new file mode 100644
index 0000000..5d24464
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-mtk-wifi-mt76-mt7996-Fix-TGax-HE-4.51.1_24G-fail.patch
@@ -0,0 +1,34 @@
+From 73aed7092e7da26eaf17b1e29bdb94222e073e94 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Fri, 17 Nov 2023 11:01:04 +0800
+Subject: [PATCH 14/23] mtk: wifi: mt76: mt7996: Fix TGax HE-4.51.1_24G fail
+
+According to sta capability to decide to enable/disable wed pao when create ppe entry.
+without this patch, TGax HE-4.51.1_24G will test fail
+
+Signed-off-by: mtk27745 <rex.lu@mediatek.com>
+---
+ mt7996/main.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 6e88420e..4db8899c 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1447,7 +1447,12 @@ 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);
++	if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU) &&
++	    mtk_wed_is_amsdu_supported(wed))
++		path->mtk_wdma.amsdu = msta->wcid.amsdu;
++	else
++		path->mtk_wdma.amsdu = 0;
++
+ 	ctx->dev = NULL;
+ 
+ 	return 0;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-mtk-wifi-mt76-mt7996-add-eagle-default-bin-of-differ.patch
similarity index 62%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-mtk-wifi-mt76-mt7996-add-eagle-default-bin-of-differ.patch
index dbef00c..b7decbf 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-wifi-mt76-mt7996-add-eagle-default-bin-of-different-.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-mtk-wifi-mt76-mt7996-add-eagle-default-bin-of-differ.patch
@@ -1,8 +1,8 @@
-From 10df4848e7a7116529e1f596e06d0d03891f502e Mon Sep 17 00:00:00 2001
+From 776233df7a3216546d93bdaf6160390736452f2a 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
+Subject: [PATCH 15/23] mtk: wifi: mt76: mt7996: add eagle default bin of
+ different sku variants
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
@@ -12,46 +12,46 @@
  3 files changed, 32 insertions(+), 2 deletions(-)
 
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 7fd318c..3276740 100644
+index 4a823711..7505a8b7 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
+@@ -26,6 +26,8 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ {
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
++		if (dev->chip_sku == MT7996_SKU_404)
++			return MT7996_EEPROM_DEFAULT_404;
  		return MT7996_EEPROM_DEFAULT;
- }
+ 	case 0x7992:
+ 		return MT7992_EEPROM_DEFAULT;
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 6d39c3c..fed74d0 100644
+index 50dcce9f..d8946a86 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);
+@@ -902,6 +902,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ 	INIT_LIST_HEAD(&dev->wed_rro.poll_list);
+ 	spin_lock_init(&dev->wed_rro.lock);
  
 +	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) &&
+ 	ret = mt7996_dma_init(dev);
+ 	if (ret)
+ 		return ret;
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 3964035..efdcff7 100644
+index 8154ad37..eab96139 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -36,6 +36,7 @@
- #define MT7996_ROM_PATCH		"mediatek/mt7996/mt7996_rom_patch.bin"
+@@ -40,6 +40,7 @@
+ #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"
+ #define MT7992_EEPROM_DEFAULT		"mediatek/mt7996/mt7992_eeprom.bin"
  #define MT7996_EEPROM_SIZE		7680
  #define MT7996_EEPROM_BLOCK_SIZE	16
-@@ -83,6 +84,11 @@ struct mt7996_sta;
+@@ -88,6 +89,11 @@ struct mt7996_sta;
  struct mt7996_dfs_pulse;
  struct mt7996_dfs_pattern;
  
@@ -62,8 +62,8 @@
 +
  enum mt7996_ram_type {
  	MT7996_RAM_TYPE_WM,
- 	MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
-@@ -264,6 +270,8 @@ struct mt7996_dev {
+ 	MT7996_RAM_TYPE_WA,
+@@ -257,6 +263,8 @@ struct mt7996_dev {
  	struct cfg80211_chan_def rdd2_chandef;
  	struct mt7996_phy *rdd2_phy;
  
@@ -72,7 +72,7 @@
  	u16 chainmask;
  	u8 chainshift[__MT_MAX_BAND];
  	u32 hif_idx;
-@@ -417,6 +425,23 @@ mt7996_phy3(struct mt7996_dev *dev)
+@@ -399,6 +407,23 @@ mt7996_phy3(struct mt7996_dev *dev)
  	return __mt7996_phy(dev, MT_BAND2);
  }
  
@@ -96,7 +96,7 @@
  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)
+@@ -406,8 +431,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
  		return band <= MT_BAND1;
  
  	/* tri-band support */
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-mtk-wifi-mt76-mt7996-add-kite-fw-default-bin-for-dif.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-mtk-wifi-mt76-mt7996-add-kite-fw-default-bin-for-dif.patch
new file mode 100644
index 0000000..7c38f4b
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-mtk-wifi-mt76-mt7996-add-kite-fw-default-bin-for-dif.patch
@@ -0,0 +1,308 @@
+From dac8a0fc54f9b171dbb57e7559db7c5245e52bbf 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 16/23] mtk: wifi: mt76: mt7996: add kite fw & default bin for
+ different sku variants
+
+Add fem type (2i5i, 2i5e, 2e5e, ...)
+Add Kite default bin for each fem type since loading wrong default bin
+will fail to setup interface
+Add eeprom fem type check
+
+Add adie 7976c efuse check
+Efuse offset 0x470 will be set to 0xc after final test if 7976c adie is used
+Chip manufactoring factories may transfer, which leads to different adie chip versions,
+so we add this efuse check to avoid 7976c recognition failure.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 35 +++++++++++++++++++++++++++--
+ mt7996/eeprom.h |  1 +
+ mt7996/init.c   | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c    |  7 +++++-
+ mt7996/mt7996.h | 49 ++++++++++++++++++++++++++---------------
+ mt7996/regs.h   |  7 ++++++
+ 6 files changed, 136 insertions(+), 21 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 7505a8b7..c8fa87ef 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -9,14 +9,30 @@
+ 
+ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ {
++#define FEM_INT				0
++#define FEM_EXT				3
+ 	u8 *eeprom = dev->mt76.eeprom.data;
++	u8 i, fem[__MT_MAX_BAND], fem_type;
+ 	u16 val = get_unaligned_le16(eeprom);
+ 
++	for (i = 0; i < __MT_MAX_BAND; i++)
++		fem[i] = eeprom[MT_EE_WIFI_CONF + 6 + i] & MT_EE_WIFI_PA_LNA_CONFIG;
++
+ 	switch (val) {
+ 	case 0x7990:
+ 		return is_mt7996(&dev->mt76) ? 0 : -EINVAL;
+ 	case 0x7992:
+-		return is_mt7992(&dev->mt76) ? 0 : -EINVAL;
++		if (fem[0] == FEM_EXT && fem[1] == FEM_EXT)
++			fem_type = MT7996_FEM_EXT;
++		else if (fem[0] == FEM_INT && fem[1] == FEM_INT)
++			fem_type = MT7996_FEM_INT;
++		else if (fem[0] == FEM_INT && fem[1] == FEM_EXT)
++			fem_type = MT7996_FEM_MIX;
++		else
++			return -EINVAL;
++
++		return (is_mt7992(&dev->mt76) ? 0 : -EINVAL) |
++		       (dev->fem_type == fem_type ? 0 : -EINVAL);
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -30,7 +46,18 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ 			return MT7996_EEPROM_DEFAULT_404;
+ 		return MT7996_EEPROM_DEFAULT;
+ 	case 0x7992:
+-		return MT7992_EEPROM_DEFAULT;
++		if (dev->chip_sku == MT7992_SKU_23) {
++			if (dev->fem_type == MT7996_FEM_INT)
++				return MT7992_EEPROM_DEFAULT_23;
++			return MT7992_EEPROM_DEFAULT_23_EXT;
++		} else if (dev->chip_sku == MT7992_SKU_44) {
++			if (dev->fem_type == MT7996_FEM_INT)
++				return MT7992_EEPROM_DEFAULT;
++			else if (dev->fem_type == MT7996_FEM_MIX)
++				return MT7992_EEPROM_DEFAULT_MIX;
++			return MT7992_EEPROM_DEFAULT_EXT;
++		}
++		return MT7992_EEPROM_DEFAULT_24;
+ 	default:
+ 		return MT7996_EEPROM_DEFAULT;
+ 	}
+@@ -221,6 +248,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ {
+ 	int ret;
+ 
++	ret = mt7996_get_chip_sku(dev);
++	if (ret)
++		return ret;
++
+ 	ret = mt7996_eeprom_load(dev);
+ 	if (ret < 0) {
+ 		if (ret != -EINVAL)
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 412d6e2f..72c38ad3 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -29,6 +29,7 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CONF0_BAND_SEL		GENMASK(2, 0)
+ #define MT_EE_WIFI_CONF1_BAND_SEL		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF2_BAND_SEL		GENMASK(2, 0)
++#define MT_EE_WIFI_PA_LNA_CONFIG		GENMASK(1, 0)
+ 
+ #define MT_EE_WIFI_CONF1_TX_PATH_BAND0		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF2_TX_PATH_BAND1		GENMASK(2, 0)
+diff --git a/mt7996/init.c b/mt7996/init.c
+index d8946a86..dae640e9 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -887,6 +887,64 @@ out:
+ #endif
+ }
+ 
++int mt7996_get_chip_sku(struct mt7996_dev *dev)
++{
++#define MT7976C_CHIP_VER	0x8a10
++#define MT7976C_HL_CHIP_VER	0x8b00
++#define MT7976C_PS_CHIP_VER	0x8c10
++#define MT7976C_EFUSE_OFFSET	0x470
++#define MT7976C_EFUSE_VALUE	0xc
++	u32 regval, val = mt76_rr(dev, MT_PAD_GPIO);
++	u16 adie_chip_id, adie_chip_ver;
++	u8 adie_comb, adie_num, adie_idx = 0;
++
++	switch (mt76_chip(&dev->mt76)) {
++	case 0x7990:
++		adie_comb = FIELD_GET(MT_PAD_GPIO_ADIE_COMB, val);
++		if (adie_comb <= 1)
++			dev->chip_sku = MT7996_SKU_444;
++		else
++			dev->chip_sku = MT7996_SKU_404;
++		break;
++	case 0x7992:
++		adie_comb = FIELD_GET(MT_PAD_GPIO_ADIE_COMB_7992, val);
++		adie_num = FIELD_GET(MT_PAD_GPIO_ADIE_NUM_7992, val);
++		adie_idx = !!adie_comb;
++		if (adie_comb)
++			dev->chip_sku = MT7992_SKU_44;
++		else if (adie_num)
++			dev->chip_sku = MT7992_SKU_23;
++		else
++			dev->chip_sku = MT7992_SKU_24;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) {
++		u8 buf[MT7996_EEPROM_BLOCK_SIZE];
++		u8 idx = MT7976C_EFUSE_OFFSET % MT7996_EEPROM_BLOCK_SIZE;
++		bool is_7976c;
++
++		mt7996_mcu_rf_regval(dev, MT_ADIE_CHIP_ID(adie_idx), &regval, false);
++		adie_chip_id = FIELD_GET(MT_ADIE_CHIP_ID_MASK, regval);
++		adie_chip_ver = FIELD_GET(MT_ADIE_VERSION_MASK, regval);
++		mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf);
++		is_7976c = (adie_chip_ver == MT7976C_CHIP_VER) ||
++			   (adie_chip_ver == MT7976C_HL_CHIP_VER) ||
++			   (adie_chip_ver == MT7976C_PS_CHIP_VER) ||
++			   (buf[idx] == MT7976C_EFUSE_VALUE);
++		if (adie_chip_id == 0x7975 || (adie_chip_id == 0x7976 && is_7976c))
++			dev->fem_type = MT7996_FEM_INT;
++		else if (adie_chip_id == 0x7977 && adie_comb == 1)
++			dev->fem_type = MT7996_FEM_MIX;
++		else
++			dev->fem_type = MT7996_FEM_EXT;
++	}
++
++	return 0;
++}
++
+ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ {
+ 	int ret, idx;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 48a1e822..8a3b9f81 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -14,7 +14,12 @@
+ 	char *_fw;						\
+ 	switch (mt76_chip(&(_dev)->mt76)) {			\
+ 	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;						\
+ 	case 0x7990:						\
+ 	default:						\
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index eab96139..c34cb76b 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -39,9 +39,24 @@
+ #define MT7992_FIRMWARE_DSP		"mediatek/mt7996/mt7992_dsp.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_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_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 MT7992_EEPROM_DEFAULT		"mediatek/mt7996/mt7992_eeprom.bin"
++#define MT7992_EEPROM_DEFAULT		"mediatek/mt7996/mt7992_eeprom_2i5i.bin"
++#define MT7992_EEPROM_DEFAULT_EXT	"mediatek/mt7996/mt7992_eeprom_2e5e.bin"
++#define MT7992_EEPROM_DEFAULT_MIX	"mediatek/mt7996/mt7992_eeprom_2i5e.bin"
++#define MT7992_EEPROM_DEFAULT_24	"mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
++#define MT7992_EEPROM_DEFAULT_23	"mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"
++#define MT7992_EEPROM_DEFAULT_23_EXT	"mediatek/mt7996/mt7992_eeprom_23_2e5e.bin"
+ #define MT7996_EEPROM_SIZE		7680
+ #define MT7996_EEPROM_BLOCK_SIZE	16
+ #define MT7996_TOKEN_SIZE		16384
+@@ -89,11 +104,24 @@ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+ struct mt7996_dfs_pattern;
+ 
++enum mt7996_fem_type {
++	MT7996_FEM_UNSET,
++	MT7996_FEM_EXT,
++	MT7996_FEM_INT,
++	MT7996_FEM_MIX,
++};
++
+ enum mt7996_sku_type {
+ 	MT7996_SKU_404,
+ 	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_WA,
+@@ -264,6 +292,7 @@ struct mt7996_dev {
+ 	struct mt7996_phy *rdd2_phy;
+ 
+ 	u8 chip_sku;
++	u8 fem_type;
+ 
+ 	u16 chainmask;
+ 	u8 chainshift[__MT_MAX_BAND];
+@@ -407,23 +436,6 @@ 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)
+ {
+@@ -462,6 +474,7 @@ 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_phy *phy);
+ int mt7996_txbf_init(struct mt7996_dev *dev);
++int mt7996_get_chip_sku(struct mt7996_dev *dev);
+ void mt7996_reset(struct mt7996_dev *dev);
+ int mt7996_run(struct ieee80211_hw *hw);
+ int mt7996_mcu_init(struct mt7996_dev *dev);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 47b429d8..cf12c5e0 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -662,6 +662,13 @@ 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)
++
++/* ADIE */
++#define MT_ADIE_CHIP_ID(_idx)                  (0x0f00002c + ((_idx) << 28))
++#define MT_ADIE_VERSION_MASK                   GENMASK(15, 0)
++#define MT_ADIE_CHIP_ID_MASK                   GENMASK(31, 16)
+ 
+ #define MT_HW_REV				0x70010204
+ #define MT_HW_REV1				0x8a00
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-mtk-wifi-mt76-mt7996-add-lock-for-indirect-register-.patch
similarity index 85%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-mtk-wifi-mt76-mt7996-add-lock-for-indirect-register-.patch
index 1a93d0b..0569291 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0014-wifi-mt76-mt7996-add-lock-for-indirect-register-acce.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-mtk-wifi-mt76-mt7996-add-lock-for-indirect-register-.patch
@@ -1,24 +1,23 @@
-From 6a8359a808df29b708b2fd2aa84c0a369be7a7d5 Mon Sep 17 00:00:00 2001
+From f6787ee5ac1f581217a0177d830c395c23183046 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
+Subject: [PATCH 17/23] mtk: 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
+index c50d89a4..d3d34f04 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)
+@@ -140,7 +140,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);
  
@@ -26,7 +25,7 @@
  	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)
+@@ -155,7 +154,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);
  
@@ -34,7 +33,7 @@
  	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)
+@@ -165,26 +163,10 @@ static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
  	return MT_HIF_REMAP_BASE_L2 + offset;
  }
  
@@ -61,7 +60,7 @@
  	if (addr < 0x100000)
  		return addr;
  
-@@ -147,6 +129,11 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
+@@ -201,6 +183,11 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
  		return dev->reg.map[i].mapped + ofs;
  	}
  
@@ -73,7 +72,7 @@
  	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,
+@@ -225,28 +212,65 @@ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
  {
  	u32 addr = __mt7996_reg_addr(dev, offset);
  
@@ -142,8 +141,8 @@
 +	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,
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+@@ -421,6 +445,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);
@@ -152,10 +151,10 @@
  	switch (device_id) {
  	case 0x7990:
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index c8e7a33..c0ceef0 100644
+index c34cb76b..7e5ec212 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -309,8 +309,7 @@ struct mt7996_dev {
+@@ -362,8 +362,7 @@ struct mt7996_dev {
  		u8 n_agrt;
  	} twt;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch
deleted file mode 100644
index 54d32c3..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0017-wifi-mt76-mt7996-get-tx_retries-and-tx_failed-from-t.patch
+++ /dev/null
@@ -1,107 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-mtk-wifi-mt76-connac-set-correct-muar_idx-for-connac.patch
similarity index 72%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-mtk-wifi-mt76-connac-set-correct-muar_idx-for-connac.patch
index 381c929..53c8e6d 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0015-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-mtk-wifi-mt76-connac-set-correct-muar_idx-for-connac.patch
@@ -1,24 +1,23 @@
-From 09a1b2d9ad49d3bea1bdd8d4f7326af6a65a3dbb Mon Sep 17 00:00:00 2001
+From 1049c0632347ba53ab8ba1d9f195377e135c9856 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 15/98] wifi: mt76: connac: set correct muar_idx for connac3
- chipset
+Subject: [PATCH 18/23] mtk: 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
 chipset.
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: I7054c3b3c64ec447cc280ea810f4958afdfa9e02
 ---
  mt76_connac.h     | 5 +++++
  mt76_connac_mcu.c | 3 +++
  2 files changed, 8 insertions(+)
 
 diff --git a/mt76_connac.h b/mt76_connac.h
-index e5ebde1..c6726ab 100644
+index fdde3d70..b1ec8d46 100644
 --- a/mt76_connac.h
 +++ b/mt76_connac.h
-@@ -245,6 +245,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
+@@ -250,6 +250,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
  	return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
  }
  
@@ -31,10 +30,10 @@
  {
  	switch (mt76_chip(dev)) {
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index bcd6c20..68de525 100644
+index 0d05404f..8dd61f86 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
-@@ -282,6 +282,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
+@@ -283,6 +283,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
  	};
  	struct sk_buff *skb;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch
deleted file mode 100644
index 5110644..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0018-wifi-mt76-mt7996-Add-mcu-commands-for-getting-sta-tx.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-mtk-wifi-mt76-mt7996-ACS-channel-time-too-long-on-du.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-mtk-wifi-mt76-mt7996-ACS-channel-time-too-long-on-du.patch
new file mode 100644
index 0000000..4cf6472
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-mtk-wifi-mt76-mt7996-ACS-channel-time-too-long-on-du.patch
@@ -0,0 +1,68 @@
+From ce1d4b6bce414015a9e889f28eafc06a57c4e1a7 Mon Sep 17 00:00:00 2001
+From: "fancy.liu" <fancy.liu@mediatek.com>
+Date: Tue, 14 Nov 2023 10:13:24 +0800
+Subject: [PATCH 19/23] mtk: wifi: mt76: mt7996: ACS channel time too long on
+ duty channel
+
+Step and issue:
+1. Set channel to 36 in hostapd config;
+2. Bootup;
+3. Enable ACS through UCI command and reload;
+4. Check hostapd log, channel 36 channel_time is much longer than other channels.
+
+Root cause:
+The reset chan_stat condition missed duty channel.
+
+Solution:
+When scan start, need to reset chan_stat in each channel switch.
+
+Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
+
+Issue:
+There's a chance that the channel time for duty channel is zero in ACS
+scan.
+
+Root cause:
+The chan_stat may be reset when restore to duty channel.
+Mac80211 will notify to hostapd when scan done and then restore to duty
+channel.
+And mt76 will clear scan flag after restore done.
+If hostapd get the chan_stat before channel_restore, will get the
+correct channel time;
+If hostapd get the chan_stat after channel_restore, will get zero
+channel time;
+
+Solution:
+When channel switch, will check the mac80211 scan state but not the mt76 scan flag.
+Mac80211 scan state will be set in scanning, and will be reset after
+scan done and before restore to duty channel.
+
+Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
+---
+ mac80211.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index cc9e9ff1..6c5b4f55 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -928,6 +928,7 @@ void mt76_set_channel(struct mt76_phy *phy)
+ 	struct cfg80211_chan_def *chandef = &hw->conf.chandef;
+ 	bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL;
+ 	int timeout = HZ / 5;
++	unsigned long was_scanning = ieee80211_get_scanning(hw);
+ 
+ 	wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
+ 	mt76_update_survey(phy);
+@@ -942,7 +943,7 @@ void mt76_set_channel(struct mt76_phy *phy)
+ 	if (!offchannel)
+ 		phy->main_chan = chandef->chan;
+ 
+-	if (chandef->chan != phy->main_chan)
++	if (chandef->chan != phy->main_chan || was_scanning)
+ 		memset(phy->chan_state, 0, sizeof(*phy->chan_state));
+ }
+ EXPORT_SYMBOL_GPL(mt76_set_channel);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch
deleted file mode 100644
index 6505422..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0019-wifi-mt76-mt7996-enable-PPDU-TxS-to-host.patch
+++ /dev/null
@@ -1,182 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-mtk-wifi-mt76-mt7996-Fixed-null-pointer-dereference-.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-mtk-wifi-mt76-mt7996-Fixed-null-pointer-dereference-.patch
new file mode 100644
index 0000000..8a6dad9
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-mtk-wifi-mt76-mt7996-Fixed-null-pointer-dereference-.patch
@@ -0,0 +1,42 @@
+From 7de61119663e923bc39f777545f39b489f9f4715 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Thu, 26 Oct 2023 10:08:10 +0800
+Subject: [PATCH 20/23] mtk: wifi: mt76: mt7996: Fixed null pointer dereference
+ issue
+
+Without this patch, when the station is still in Authentication stage and
+sends a "Notify bandwidth change action frame" to AP at the same time,
+there will be a race condition that causes a crash to occur because the AP
+access "msta->vif" that has not been fully initialized.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Signed-off-by: Money Wang <money.wang@mediatek.com>
+Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
+---
+ mt7996/main.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 4db8899c..9fbd87d5 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1063,9 +1063,16 @@ static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
+ 				 struct ieee80211_sta *sta,
+ 				 u32 changed)
+ {
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 	struct mt7996_dev *dev = phy->dev;
+ 
++	if (!msta->vif) {
++		dev_warn(dev->mt76.dev, "Un-initialized STA %pM wcid %d in rc_work\n",
++			 sta->addr, msta->wcid.idx);
++		return;
++	}
++
+ 	mt7996_sta_rc_work(&changed, sta);
+ 	ieee80211_queue_work(hw, &dev->rc_work);
+ }
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch
deleted file mode 100644
index 5cee6a0..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0020-wifi-mt76-mt7996-fix-incorrect-report-of-TX-GI.patch
+++ /dev/null
@@ -1,233 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-mtk-wifi-mt76-add-sanity-check-to-prevent-kernel-cra.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-mtk-wifi-mt76-add-sanity-check-to-prevent-kernel-cra.patch
new file mode 100644
index 0000000..b12d5ed
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-mtk-wifi-mt76-add-sanity-check-to-prevent-kernel-cra.patch
@@ -0,0 +1,36 @@
+From 56cd8feb0565b8eedfae7c42dba8b5e374dc71a8 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 30 Oct 2023 11:06:19 +0800
+Subject: [PATCH 21/23] mtk: wifi: mt76: add sanity check to prevent kernel
+ crash
+
+wcid may not be initialized when mac80211 calls mt76.tx and it would lead to
+kernel crash.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ tx.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/tx.c b/tx.c
+index 1809b032..4596b367 100644
+--- a/tx.c
++++ b/tx.c
+@@ -345,6 +345,14 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
+ 
+ 	info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
+ 
++	if (!wcid->tx_pending.prev || !wcid->tx_pending.next) {
++		dev_warn(phy->dev->dev, "Un-initialized STA %pM wcid %d in mt76_tx\n",
++			 sta->addr, wcid->idx);
++
++		ieee80211_free_txskb(phy->hw, skb);
++		return;
++	}
++
+ 	spin_lock_bh(&wcid->tx_pending.lock);
+ 	__skb_queue_tail(&wcid->tx_pending, skb);
+ 	spin_unlock_bh(&wcid->tx_pending.lock);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch
deleted file mode 100644
index a5a8417..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0021-wifi-mt76-mt7996-remove-periodic-MPDU-TXS-request.patch
+++ /dev/null
@@ -1,119 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-mtk-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
similarity index 94%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-mtk-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
index a850a6c..5f22e8e 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0016-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0022-mtk-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
@@ -1,10 +1,9 @@
-From 4d055393b680ce616cb96f75cca154016cfb9a68 Mon Sep 17 00:00:00 2001
+From 8795ba8431696203ecd0b5bbf37ad64302250a29 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 16/98] wifi: mt76: mt7996: add firmware WA's coredump.
+Subject: [PATCH 22/23] mtk: wifi: mt76: mt7996: add firmware WA's coredump.
 
 Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
-Change-Id: I51f115b4ae15bc0f871f93652570d72511dbf880
 ---
  mt7996/coredump.c | 180 ++++++++++++++++++++++++++++++----------------
  mt7996/coredump.h |  35 ++++++---
@@ -15,7 +14,7 @@
  6 files changed, 182 insertions(+), 83 deletions(-)
 
 diff --git a/mt7996/coredump.c b/mt7996/coredump.c
-index ccab0d7..60b8808 100644
+index ccab0d7b..60b88085 100644
 --- a/mt7996/coredump.c
 +++ b/mt7996/coredump.c
 @@ -7,11 +7,11 @@
@@ -336,7 +335,7 @@
  }
  
 diff --git a/mt7996/coredump.h b/mt7996/coredump.h
-index af2ba21..01ed373 100644
+index af2ba219..01ed3731 100644
 --- a/mt7996/coredump.h
 +++ b/mt7996/coredump.h
 @@ -6,10 +6,13 @@
@@ -429,10 +428,10 @@
  	return NULL;
  }
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-index ccb7b22..066955e 100644
+index 19b34066..adbfd23f 100644
 --- a/mt7996/mac.c
 +++ b/mt7996/mac.c
-@@ -1962,28 +1962,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
+@@ -2001,28 +2001,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
  }
  
  /* firmware coredump */
@@ -465,7 +464,7 @@
  	if (!mem_region || !crash_data->memdump_buf_len) {
  		mutex_unlock(&dev->dump_mutex);
  		goto skip_memdump;
-@@ -1993,6 +1990,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2032,6 +2029,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
  	buf_len = crash_data->memdump_buf_len;
  
  	/* dumping memory content... */
@@ -475,7 +474,7 @@
  	memset(buf, 0, buf_len);
  	for (i = 0; i < num; i++) {
  		if (mem_region->len > buf_len) {
-@@ -2009,6 +2009,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2048,6 +2048,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
  		mt7996_memcpy_fromio(dev, buf, mem_region->start,
  				     mem_region->len);
  
@@ -483,7 +482,7 @@
  		hdr->start = mem_region->start;
  		hdr->len = mem_region->len;
  
-@@ -2025,8 +2026,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2064,8 +2065,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
  	mutex_unlock(&dev->dump_mutex);
  
  skip_memdump:
@@ -507,10 +506,10 @@
  }
  
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index ee1915c..2c611e7 100644
+index 8a3b9f81..475a5e18 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -2458,6 +2458,8 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
+@@ -2697,6 +2697,8 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
  
  	dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
  		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
@@ -519,7 +518,7 @@
  
  	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
  		struct mt7996_patch_sec *sec;
-@@ -2584,6 +2586,9 @@ static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
+@@ -2823,6 +2825,9 @@ static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
  	}
  
  	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
@@ -530,10 +529,10 @@
  		 fw_type, hdr->fw_ver, hdr->build_date);
  
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index c0ceef0..0bb20a9 100644
+index 7e5ec212..e1610d3b 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -57,6 +57,8 @@
+@@ -83,6 +83,8 @@
  #define MT7996_CRIT_TEMP		110
  #define MT7996_MAX_TEMP			120
  
@@ -542,7 +541,7 @@
  #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 {
+@@ -126,6 +128,7 @@ enum mt7996_ram_type {
  	MT7996_RAM_TYPE_WM,
  	MT7996_RAM_TYPE_WA,
  	MT7996_RAM_TYPE_DSP,
@@ -550,7 +549,7 @@
  };
  
  enum mt7996_txq_id {
-@@ -265,9 +268,11 @@ struct mt7996_dev {
+@@ -316,9 +319,11 @@ struct mt7996_dev {
  	struct mutex dump_mutex;
  #ifdef CONFIG_DEV_COREDUMP
  	struct {
@@ -564,10 +563,10 @@
  	struct list_head sta_rc_list;
  	struct list_head twt_list;
 diff --git a/mt7996/regs.h b/mt7996/regs.h
-index f7c99cd..bd0eb51 100644
+index cf12c5e0..4c20a67d 100644
 --- a/mt7996/regs.h
 +++ b/mt7996/regs.h
-@@ -548,7 +548,8 @@ enum base_rev {
+@@ -597,7 +597,8 @@ enum offs_rev {
  
  /* FW MODE SYNC */
  #define MT_FW_ASSERT_CNT			0x02208274
@@ -577,7 +576,7 @@
  
  #define MT_SWDEF_BASE				0x00401400
  
-@@ -656,11 +657,15 @@ enum base_rev {
+@@ -714,11 +715,15 @@ enum offs_rev {
  #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR		BIT(29)
  
  /* CONN MCU EXCP CON */
@@ -592,7 +591,7 @@
 +#define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS	GENMASK(20, 16)
  #define MT_MCU_WM_EXCP_LR_LOG			MT_MCU_WM_EXCP(0x204)
  
- #endif
+ /* CONN AFE CTL CON */
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch
similarity index 78%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch
index 7b88df9..9e70644 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0029-wifi-mt76-mt7996-add-preamble-puncture-support-for-m.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0023-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch
@@ -1,8 +1,8 @@
-From ee2e6d4d137cadf56c1c102d73761f76fd97a6ea Mon Sep 17 00:00:00 2001
+From d83b800e9615b4d861fd79c5f71e26cd8d0c4141 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
+Subject: [PATCH 23/23] mtk: wifi: mt76: mt7996: add preamble puncture support
+ for mt7996
 
 Add support configure preamble puncture feature through mcu commands.
 
@@ -15,10 +15,10 @@
  4 files changed, 37 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 8562ca4..6fac67b 100644
+index 84e77fa0..823b3626 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1241,6 +1241,7 @@ enum {
+@@ -1259,6 +1259,7 @@ enum {
  	MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
  	MCU_UNI_CMD_THERMAL = 0x35,
  	MCU_UNI_CMD_VOW = 0x37,
@@ -27,12 +27,12 @@
  	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
+index 475a5e18..deabdb1f 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);
+@@ -4534,3 +4534,33 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ 	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ 				     MCU_WM_UNI_CMD(TXPOWER), true);
  }
 +
 +int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, bool auto_mode,
@@ -65,10 +65,10 @@
 +				 &req, sizeof(req), false);
 +}
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 376931e..296acbd 100644
+index a9ba63d1..238c4c53 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -845,6 +845,10 @@ enum {
+@@ -923,6 +923,10 @@ enum {
  	MT7996_SEC_MODE_MAX,
  };
  
@@ -80,10 +80,10 @@
  #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
+index e1610d3b..4176e51a 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,
+@@ -654,6 +654,8 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_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);
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0024-wifi-mt76-mt7996-add-kite-pci-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0024-wifi-mt76-mt7996-add-kite-pci-support.patch
deleted file mode 100644
index d3c12af..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0024-wifi-mt76-mt7996-add-kite-pci-support.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch
deleted file mode 100644
index 7ce6401..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0025-wifi-mt76-mt7996-add-kite-wtbl-size-support.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch
deleted file mode 100644
index d494783..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0026-wifi-mt76-mt7996-accommodate-MT7992-with-different-c.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch
deleted file mode 100644
index 3f5cfe7..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0027-wifi-mt76-mt7996-add-AFE-pll-enable-before-driver-ow.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch
deleted file mode 100644
index 9d0f02b..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0028-wifi-mt76-mt7996-add-kite-eagle-CR-offset-revision.patch
+++ /dev/null
@@ -1,232 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch
deleted file mode 100644
index 0789ad2..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0030-wifi-mt76-mt7996-fix-all-sta-info-struct-alignment.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch
deleted file mode 100644
index 8e716a0..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0031-wifi-mt76-mt7996-refine-ampdu-factor.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-wifi-mt76-mt7996-for-build-pass.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-mtk-wifi-mt76-mt7996-for-build-pass.patch
similarity index 82%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-wifi-mt76-mt7996-for-build-pass.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-mtk-wifi-mt76-mt7996-for-build-pass.patch
index 48ca34e..f414f45 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-wifi-mt76-mt7996-for-build-pass.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/0999-mtk-wifi-mt76-mt7996-for-build-pass.patch
@@ -1,9 +1,8 @@
-From fd11038a011cf006ee347a48d880c38a2ad20c75 Mon Sep 17 00:00:00 2001
+From bb8cbd2687b9601b8970cb9be1cfd356f285997e 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 32/98] wifi: mt76: mt7996: for build pass
+Subject: [PATCH 0999/1041] mtk: wifi: mt76: mt7996: for build pass
 
-Change-Id: Ieb44c33ee6e6a2e6058c1ef528404c1a1cbcfdaf
 ---
  debugfs.c         | 3 +++
  dma.c             | 2 +-
@@ -18,7 +17,7 @@
  10 files changed, 19 insertions(+), 4 deletions(-)
 
 diff --git a/debugfs.c b/debugfs.c
-index c4649ba..ac5207e 100644
+index c4649ba0..ac5207e5 100644
 --- a/debugfs.c
 +++ b/debugfs.c
 @@ -33,8 +33,11 @@ mt76_napi_threaded_set(void *data, u64 val)
@@ -34,10 +33,10 @@
  	return 0;
  }
 diff --git a/dma.c b/dma.c
-index dd20271..bb995e2 100644
+index 00230f10..12f0e2fd 100644
 --- a/dma.c
 +++ b/dma.c
-@@ -943,7 +943,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -960,7 +960,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 +46,10 @@
  			goto free_frag;
  
 diff --git a/eeprom.c b/eeprom.c
-index 2558788..a07ca84 100644
+index 0bc66cc1..7d5cf28f 100644
 --- a/eeprom.c
 +++ b/eeprom.c
-@@ -161,9 +161,15 @@ void
+@@ -163,9 +163,15 @@ void
  mt76_eeprom_override(struct mt76_phy *phy)
  {
  	struct mt76_dev *dev = phy->dev;
@@ -68,7 +67,7 @@
  	if (!is_valid_ether_addr(phy->macaddr)) {
  		eth_random_addr(phy->macaddr);
 diff --git a/mcu.c b/mcu.c
-index a8cafa3..fa4b054 100644
+index a8cafa39..fa4b0544 100644
 --- a/mcu.c
 +++ b/mcu.c
 @@ -4,6 +4,7 @@
@@ -80,7 +79,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 955974a..db337aa 100644
+index ae34d019..c9444c6d 100644
 --- a/mt7615/mcu.c
 +++ b/mt7615/mcu.c
 @@ -10,6 +10,7 @@
@@ -92,7 +91,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 bb570f2..236cfea 100644
+index 8dd61f86..52237583 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -4,6 +4,7 @@
@@ -104,7 +103,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 b6fba1a..dee01e0 100644
+index 09badb16..2718ba52 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -6,6 +6,7 @@
@@ -116,10 +115,10 @@
  #define fw_name(_dev, name, ...)	({			\
  	char *_fw;						\
 diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 1ed91da..23f6f16 100644
+index 483ad81b..8e29ab06 100644
 --- a/mt7996/dma.c
 +++ b/mt7996/dma.c
-@@ -602,8 +602,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+@@ -640,8 +640,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
  	if (ret < 0)
  		return ret;
  
@@ -131,10 +130,10 @@
  
  	mt7996_dma_enable(dev, false);
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index ca0e9d0..7ae92e1 100644
+index c8fa87ef..7d07c1b1 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
-@@ -98,6 +98,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
+@@ -135,6 +135,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
  	if (ret)
  		return ret;
  
@@ -143,7 +142,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 8b81644..fdc4fb4 100644
+index deabdb1f..3ecdde86 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
 @@ -5,6 +5,7 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-wifi-mt76-mt7996-add-debug-tool.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch
similarity index 93%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-wifi-mt76-mt7996-add-debug-tool.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch
index d29a90b..6b5ad66 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-wifi-mt76-mt7996-add-debug-tool.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch
@@ -1,29 +1,71 @@
-From 393f2e0f06e9a6ead8ffd64c904b6e24ff6c92f1 Mon Sep 17 00:00:00 2001
+From a4b26d99f6d02c2b4e7ebff9a07acbdd7ec5185b 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 33/98] wifi: mt76: mt7996: add debug tool
+Subject: [PATCH 1000/1041] mtk: wifi: mt76: mt7996: add debug tool
 
-Change-Id: Ie10390b01f17db893dbfbf3221bf63a4bd1fe38f
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Add PSM bit in sta_info
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+
+Remove the duplicate function in mtk_debugfs.c & mtk_debug_i.c
+Only enable mt7996_mcu_fw_log_2_host function in mcu.c
+
+Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
+
+Support more ids category NDPA/NDP TXD/FBK and debug log recommended by
+CTD members.
+
+This commit equals to run the follwoing commands on Logan driver:
+command:
+1. iwpriv ra0 set fw_dbg=1:84
+2. iwpriv ra0 set fw_dbg=2:84
+3. iwpriv ra0 set fw_dbg=1:101
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+
+mtk: wifi: mt76: mt7996: add wtbl_info support for mt7992
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+mtk: wifi: mt76: mt7996: add mt7992 & mt7996 CR debug offset revision
+
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
+ mt76.h               |    2 +
  mt7996/Makefile      |    4 +
  mt7996/coredump.c    |   10 +-
  mt7996/coredump.h    |    7 +
- mt7996/debugfs.c     |   34 +-
- mt7996/mt7996.h      |   10 +
- mt7996/mtk_debug.h   | 2147 ++++++++++++++++++++++++++++++++++++++
- mt7996/mtk_debugfs.c | 2379 ++++++++++++++++++++++++++++++++++++++++++
+ mt7996/debugfs.c     |   66 +-
+ mt7996/mac.c         |    3 +
+ mt7996/mt7996.h      |   11 +
+ mt7996/mtk_debug.h   | 2286 ++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_debugfs.c | 2484 ++++++++++++++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.c     |   18 +
  mt7996/mtk_mcu.h     |   16 +
  tools/fwlog.c        |   25 +-
- 10 files changed, 4630 insertions(+), 20 deletions(-)
+ 12 files changed, 4907 insertions(+), 25 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/mt76.h b/mt76.h
+index d2ead585..de0021e4 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -393,6 +393,8 @@ struct mt76_txwi_cache {
+ 		struct sk_buff *skb;
+ 		void *ptr;
+ 	};
++
++	unsigned long jiffies;
+ };
+ 
+ struct mt76_rx_tid {
 diff --git a/mt7996/Makefile b/mt7996/Makefile
-index 07c8b55..a056b40 100644
+index 07c8b555..a056b40e 100644
 --- a/mt7996/Makefile
 +++ b/mt7996/Makefile
 @@ -1,4 +1,6 @@
@@ -40,7 +82,7 @@
 +
 +mt7996e-y += mtk_debugfs.o mtk_mcu.o
 diff --git a/mt7996/coredump.c b/mt7996/coredump.c
-index 60b8808..a7f91b5 100644
+index 60b88085..a7f91b56 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
@@ -89,7 +131,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 01ed373..93cd84a 100644
+index 01ed3731..93cd84a0 100644
 --- a/mt7996/coredump.h
 +++ b/mt7996/coredump.h
 @@ -75,6 +75,7 @@ struct mt7996_mem_region {
@@ -114,22 +156,42 @@
  mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
  {
 diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 9bd9535..92aa164 100644
+index 9bd95358..c4b82cb2 100644
 --- a/mt7996/debugfs.c
 +++ b/mt7996/debugfs.c
-@@ -290,11 +290,20 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
+@@ -290,11 +290,39 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
  		DEBUG_SPL,
  		DEBUG_RPT_RX,
  		DEBUG_RPT_RA = 68,
+-	} debug;
++		DEBUG_IDS_SND = 84,
 +		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;
++		DEBUG_IDS_ERR_LOG = 101,
++	};
++	u8 debug_category[] = {
++		DEBUG_TXCMD,
++		DEBUG_CMD_RPT_TX,
++		DEBUG_CMD_RPT_TRIG,
++		DEBUG_SPL,
++		DEBUG_RPT_RX,
++		DEBUG_RPT_RA,
++		DEBUG_IDS_SND,
++		DEBUG_IDS_PP,
++		DEBUG_IDS_RA,
++		DEBUG_IDS_BF,
++		DEBUG_IDS_SR,
++		DEBUG_IDS_RU,
++		DEBUG_IDS_MUMIMO,
++		DEBUG_IDS_ERR_LOG,
++	};
  	bool tx, rx, en;
  	int ret;
++	u8 i;
  
  	dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
 +#ifdef CONFIG_MTK_DEBUG
@@ -138,18 +200,35 @@
  
  	if (dev->fw_debug_bin)
  		val = MCU_FW_LOG_RELAY;
-@@ -309,8 +318,8 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
+@@ -309,18 +337,21 @@ 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;
+-			continue;
+-
+-		if (debug == DEBUG_RPT_RX)
++	for (i = 0; i < ARRAY_SIZE(debug_category); i++) {
++		if (debug_category[i] == DEBUG_RPT_RX)
+ 			val = en && rx;
+ 		else
+ 			val = en && tx;
  
- 		if (debug == DEBUG_RPT_RX)
-@@ -401,11 +410,12 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
+-		ret = mt7996_mcu_fw_dbg_ctrl(dev, debug, val);
++		ret = mt7996_mcu_fw_dbg_ctrl(dev, debug_category[i], val);
+ 		if (ret)
+ 			return ret;
++
++		if (debug_category[i] == DEBUG_IDS_SND && en) {
++			ret = mt7996_mcu_fw_dbg_ctrl(dev, debug_category[i], 2);
++			if (ret)
++				return ret;
++		}
+ 	}
+ 
+ 	return 0;
+@@ -401,11 +432,12 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
  	};
  	struct mt7996_dev *dev = data;
  
@@ -165,7 +244,7 @@
  
  	dev->fw_debug_bin = val;
  
-@@ -819,6 +829,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+@@ -819,6 +851,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
  	if (phy == &dev->phy)
  		dev->debugfs_dir = dir;
  
@@ -177,7 +256,7 @@
  	return 0;
  }
  
-@@ -831,6 +846,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
+@@ -831,6 +868,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
  	void *dest;
  
  	spin_lock_irqsave(&lock, flags);
@@ -190,7 +269,7 @@
  	dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
  	if (dest) {
  		*(u32 *)dest = hdrlen + len;
-@@ -863,9 +884,6 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
+@@ -863,9 +906,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),
  	};
  
@@ -200,11 +279,25 @@
  	hdr.serial_id = cpu_to_le16(dev->fw_debug_seq++);
  	hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0)));
  	hdr.len = *(__le16 *)data;
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index adbfd23f..ce6759e0 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -936,6 +936,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 	id = mt76_token_consume(mdev, &t);
+ 	if (id < 0)
+ 		return id;
++#ifdef CONFIG_MTK_DEBUG
++	t->jiffies = jiffies;
++#endif
+ 
+ 	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+ 	memset(txwi_ptr, 0, MT_TXD_SIZE);
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index c4d74a0..8801956 100644
+index 4176e51a..34159f97 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -317,6 +317,16 @@ struct mt7996_dev {
+@@ -370,6 +370,17 @@ struct mt7996_dev {
  	spinlock_t reg_lock;
  
  	u8 wtbl_size_group;
@@ -217,16 +310,17 @@
 +		u8 fw_dbg_lv;
 +		u32 bcn_total_cnt[__MT_MAX_BAND];
 +	} dbg;
++	const struct mt7996_dbg_reg_desc *dbg_reg;
 +#endif
  };
  
  enum {
 diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
 new file mode 100644
-index 0000000..368f0bc
+index 00000000..27d8f1cb
 --- /dev/null
 +++ b/mt7996/mtk_debug.h
-@@ -0,0 +1,2147 @@
+@@ -0,0 +1,2286 @@
 +#ifndef __MTK_DEBUG_H
 +#define __MTK_DEBUG_H
 +
@@ -239,6 +333,123 @@
 +		(((_reg) & (_field##_MASK)) >> (_field##_SHIFT));	\
 +	})
 +
++#define __DBG_OFFS(id)		(dev->dbg_reg->offs_rev[(id)])
++
++enum dbg_offs_rev {
++	AGG_AALCR2,
++	AGG_AALCR3,
++	AGG_AALCR4,
++	AGG_AALCR5,
++	AGG_AALCR6,
++	AGG_AALCR7,
++	MIB_TDRCR0,
++	MIB_TDRCR1,
++	MIB_TDRCR2,
++	MIB_TDRCR3,
++	MIB_TDRCR4,
++	MIB_RSCR26,
++	MIB_TSCR18,
++	MIB_TRDR0,
++	MIB_TRDR2,
++	MIB_TRDR3,
++	MIB_TRDR4,
++	MIB_TRDR5,
++	MIB_TRDR6,
++	MIB_TRDR7,
++	MIB_TRDR8,
++	MIB_TRDR9,
++	MIB_TRDR10,
++	MIB_TRDR11,
++	MIB_TRDR12,
++	MIB_TRDR13,
++	MIB_TRDR14,
++	MIB_TRDR15,
++	MIB_MSR0,
++	MIB_MSR1,
++	MIB_MSR2,
++	MIB_MCTR5,
++	MIB_MCTR6,
++	__MT_DBG_OFFS_REV_MAX,
++};
++
++static const u32 mt7996_dbg_offs[] = {
++	[AGG_AALCR2]		= 0x128,
++	[AGG_AALCR3]		= 0x12c,
++	[AGG_AALCR4]		= 0x130,
++	[AGG_AALCR5]		= 0x134,
++	[AGG_AALCR6]		= 0x138,
++	[AGG_AALCR7]		= 0x13c,
++	[MIB_TDRCR0]		= 0x728,
++	[MIB_TDRCR1]		= 0x72c,
++	[MIB_TDRCR2]		= 0x730,
++	[MIB_TDRCR3]		= 0x734,
++	[MIB_TDRCR4]		= 0x738,
++	[MIB_RSCR26]		= 0x950,
++	[MIB_TSCR18]		= 0xa1c,
++	[MIB_TRDR0]		= 0xa24,
++	[MIB_TRDR2]		= 0xa2c,
++	[MIB_TRDR3]		= 0xa30,
++	[MIB_TRDR4]		= 0xa34,
++	[MIB_TRDR5]		= 0xa38,
++	[MIB_TRDR6]		= 0xa3c,
++	[MIB_TRDR7]		= 0xa40,
++	[MIB_TRDR8]		= 0xa44,
++	[MIB_TRDR9]		= 0xa48,
++	[MIB_TRDR10]		= 0xa4c,
++	[MIB_TRDR11]		= 0xa50,
++	[MIB_TRDR12]		= 0xa54,
++	[MIB_TRDR13]		= 0xa58,
++	[MIB_TRDR14]		= 0xa5c,
++	[MIB_TRDR15]		= 0xa60,
++	[MIB_MSR0]		= 0xa64,
++	[MIB_MSR1]		= 0xa68,
++	[MIB_MSR2]		= 0xa6c,
++	[MIB_MCTR5]		= 0xa70,
++	[MIB_MCTR6]		= 0xa74,
++};
++
++static const u32 mt7992_dbg_offs[] = {
++	[AGG_AALCR2]		= 0x12c,
++	[AGG_AALCR3]		= 0x130,
++	[AGG_AALCR4]		= 0x134,
++	[AGG_AALCR5]		= 0x138,
++	[AGG_AALCR6]		= 0x13c,
++	[AGG_AALCR7]		= 0x140,
++	[MIB_TDRCR0]		= 0x768,
++	[MIB_TDRCR1]		= 0x76c,
++	[MIB_TDRCR2]		= 0x770,
++	[MIB_TDRCR3]		= 0x774,
++	[MIB_TDRCR4]		= 0x778,
++	[MIB_RSCR26]		= 0x994,
++	[MIB_TSCR18]		= 0xb18,
++	[MIB_TRDR0]		= 0xb20,
++	[MIB_TRDR2]		= 0xb28,
++	[MIB_TRDR3]		= 0xb2c,
++	[MIB_TRDR4]		= 0xb30,
++	[MIB_TRDR5]		= 0xb34,
++	[MIB_TRDR6]		= 0xb38,
++	[MIB_TRDR7]		= 0xb3c,
++	[MIB_TRDR8]		= 0xb40,
++	[MIB_TRDR9]		= 0xb44,
++	[MIB_TRDR10]		= 0xb48,
++	[MIB_TRDR11]		= 0xb4c,
++	[MIB_TRDR12]		= 0xb50,
++	[MIB_TRDR13]		= 0xb54,
++	[MIB_TRDR14]		= 0xb58,
++	[MIB_TRDR15]		= 0xb5c,
++	[MIB_MSR0]		= 0xb60,
++	[MIB_MSR1]		= 0xb64,
++	[MIB_MSR2]		= 0xb68,
++	[MIB_MCTR5]		= 0xb6c,
++	[MIB_MCTR6]		= 0xb70,
++};
++
++/* used to differentiate between generations */
++struct mt7996_dbg_reg_desc {
++	const u32 id;
++	const u32 *offs_rev;
++};
++
 +/* AGG */
 +#define BN0_WF_AGG_TOP_BASE                                    0x820e2000
 +#define BN1_WF_AGG_TOP_BASE                                    0x820f2000
@@ -309,12 +520,12 @@
 +#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_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_AALCR2_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR2))
++#define BN0_WF_AGG_TOP_AALCR3_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR3))
++#define BN0_WF_AGG_TOP_AALCR4_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR4))
++#define BN0_WF_AGG_TOP_AALCR5_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR5))
++#define BN0_WF_AGG_TOP_AALCR6_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR6))
++#define BN0_WF_AGG_TOP_AALCR7_ADDR                             (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR7))
 +#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
@@ -838,7 +1049,7 @@
 +#define BN0_WF_MIB_TOP_BTBCR_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x450) // D450
 +#define BN0_WF_MIB_TOP_BTDCR_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x590) // D590
 +#define BN0_WF_MIB_TOP_BTCR_ADDR                               (BN0_WF_MIB_TOP_BASE + 0x5A0) // D5A0
-+#define BN0_WF_MIB_TOP_RVSR0_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x720) // D720
++#define BN0_WF_MIB_TOP_RVSR0_ADDR                              (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RVSR0))
 +
 +#define BN0_WF_MIB_TOP_TSCR0_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x6B0) // D6B0
 +#define BN0_WF_MIB_TOP_TSCR3_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x6BC) // D6BC
@@ -854,37 +1065,37 @@
 +#define BN0_WF_MIB_TOP_TBCR3_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x6F8) // D6F8
 +#define BN0_WF_MIB_TOP_TBCR4_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x6FC) // D6FC
 +
-+#define BN0_WF_MIB_TOP_TDRCR0_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x728) // D728
-+#define BN0_WF_MIB_TOP_TDRCR1_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x72C) // D72C
-+#define BN0_WF_MIB_TOP_TDRCR2_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x730) // D730
-+#define BN0_WF_MIB_TOP_TDRCR3_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x734) // D734
-+#define BN0_WF_MIB_TOP_TDRCR4_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x738) // D738
++#define BN0_WF_MIB_TOP_TDRCR0_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR0))
++#define BN0_WF_MIB_TOP_TDRCR1_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR1))
++#define BN0_WF_MIB_TOP_TDRCR2_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR2))
++#define BN0_WF_MIB_TOP_TDRCR3_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR3))
++#define BN0_WF_MIB_TOP_TDRCR4_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR4))
 +
 +#define BN0_WF_MIB_TOP_BTSCR0_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x5E0) // D5E0
 +#define BN0_WF_MIB_TOP_BTSCR1_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x5F0) // D5F0
 +#define BN0_WF_MIB_TOP_BTSCR2_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x600) // D600
 +#define BN0_WF_MIB_TOP_BTSCR3_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x610) // D610
 +#define BN0_WF_MIB_TOP_BTSCR4_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x620) // D620
-+#define BN0_WF_MIB_TOP_BTSCR5_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x788) // D788
-+#define BN0_WF_MIB_TOP_BTSCR6_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x798) // D798
++#define BN0_WF_MIB_TOP_BTSCR5_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BTSCR5))
++#define BN0_WF_MIB_TOP_BTSCR6_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BTSCR6))
 +
-+#define BN0_WF_MIB_TOP_RSCR1_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x7AC) // D7AC
-+#define BN0_WF_MIB_TOP_BSCR2_ADDR                              (BN0_WF_MIB_TOP_BASE + 0x9D4) // D9D4
-+#define BN0_WF_MIB_TOP_TSCR18_ADDR                             (BN0_WF_MIB_TOP_BASE + 0xA1C) // DA1C
++#define BN0_WF_MIB_TOP_RSCR1_ADDR                              (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR1))
++#define BN0_WF_MIB_TOP_BSCR2_ADDR                              (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BSCR2))
++#define BN0_WF_MIB_TOP_TSCR18_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TSCR18))
 +
-+#define BN0_WF_MIB_TOP_MSR0_ADDR                               (BN0_WF_MIB_TOP_BASE + 0xA64) // DA64
-+#define BN0_WF_MIB_TOP_MSR1_ADDR                               (BN0_WF_MIB_TOP_BASE + 0xA68) // DA68
-+#define BN0_WF_MIB_TOP_MSR2_ADDR                               (BN0_WF_MIB_TOP_BASE + 0xA6C) // DA6C
-+#define BN0_WF_MIB_TOP_MCTR5_ADDR                              (BN0_WF_MIB_TOP_BASE + 0xA70) // DA70
-+#define BN0_WF_MIB_TOP_MCTR6_ADDR                              (BN0_WF_MIB_TOP_BASE + 0xA74) // DA74
++#define BN0_WF_MIB_TOP_MSR0_ADDR                               (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR0))
++#define BN0_WF_MIB_TOP_MSR1_ADDR                               (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR1))
++#define BN0_WF_MIB_TOP_MSR2_ADDR                               (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR2))
++#define BN0_WF_MIB_TOP_MCTR5_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MCTR5))
++#define BN0_WF_MIB_TOP_MCTR6_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MCTR6))
 +
-+#define BN0_WF_MIB_TOP_RSCR26_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x950) // D950
-+#define BN0_WF_MIB_TOP_RSCR27_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x954) // D954
-+#define BN0_WF_MIB_TOP_RSCR28_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x958) // D958
-+#define BN0_WF_MIB_TOP_RSCR31_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x964) // D964
-+#define BN0_WF_MIB_TOP_RSCR33_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x96C) // D96C
-+#define BN0_WF_MIB_TOP_RSCR35_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x974) // D974
-+#define BN0_WF_MIB_TOP_RSCR36_ADDR                             (BN0_WF_MIB_TOP_BASE + 0x978) // D978
++#define BN0_WF_MIB_TOP_RSCR26_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_RSCR26))
++#define BN0_WF_MIB_TOP_RSCR27_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR27))
++#define BN0_WF_MIB_TOP_RSCR28_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR28))
++#define BN0_WF_MIB_TOP_RSCR31_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR31))
++#define BN0_WF_MIB_TOP_RSCR33_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR33))
++#define BN0_WF_MIB_TOP_RSCR35_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR35))
++#define BN0_WF_MIB_TOP_RSCR36_ADDR                             (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR36))
 +
 +#define BN0_WF_MIB_TOP_TSCR3_AMPDU_MPDU_COUNT_MASK             0xFFFFFFFF                // AMPDU_MPDU_COUNT[31..0]
 +#define BN0_WF_MIB_TOP_TSCR4_AMPDU_ACKED_COUNT_MASK            0xFFFFFFFF                // AMPDU_ACKED_COUNT[31..0]
@@ -926,22 +1137,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 + 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_TRDR0_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR0))
++#define BN0_WF_MIB_TOP_TRDR1_ADDR                              (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_TRDR1))
++#define BN0_WF_MIB_TOP_TRDR2_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR2))
++#define BN0_WF_MIB_TOP_TRDR3_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR3))
++#define BN0_WF_MIB_TOP_TRDR4_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR4))
++#define BN0_WF_MIB_TOP_TRDR5_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR5))
++#define BN0_WF_MIB_TOP_TRDR6_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR6))
++#define BN0_WF_MIB_TOP_TRDR7_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR7))
++#define BN0_WF_MIB_TOP_TRDR8_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR8))
++#define BN0_WF_MIB_TOP_TRDR9_ADDR                              (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR9))
++#define BN0_WF_MIB_TOP_TRDR10_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR10))
++#define BN0_WF_MIB_TOP_TRDR11_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR11))
++#define BN0_WF_MIB_TOP_TRDR12_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR12))
++#define BN0_WF_MIB_TOP_TRDR13_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR13))
++#define BN0_WF_MIB_TOP_TRDR14_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR14))
++#define BN0_WF_MIB_TOP_TRDR15_ADDR                             (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR15))
 +
 +#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]
@@ -1063,7 +1274,7 @@
 +};
 +
 +#define LWTBL_LEN_IN_DW			36
-+#define UWTBL_LEN_IN_DW			10
++#define UWTBL_LEN_IN_DW			16
 +
 +#define MT_DBG_WTBL_BASE		0x820D8000
 +
@@ -1317,6 +1528,17 @@
 +#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 \
@@ -1534,6 +1756,8 @@
 +#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
@@ -1794,16 +2018,25 @@
 +#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 \
@@ -2376,10 +2609,10 @@
 +#endif
 diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
 new file mode 100644
-index 0000000..5aa5c94
+index 00000000..53b11d54
 --- /dev/null
 +++ b/mt7996/mtk_debugfs.c
-@@ -0,0 +1,2379 @@
+@@ -0,0 +1,2484 @@
 +// SPDX-License-Identifier: ISC
 +/*
 + * Copyright (C) 2023 MediaTek Inc.
@@ -3393,7 +3626,8 @@
 +	}
 +}
 +
-+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},
@@ -3414,6 +3648,26 @@
 +	{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;
@@ -3523,7 +3777,8 @@
 +	}
 +}
 +
-+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},
@@ -3545,6 +3800,27 @@
 +	{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;
@@ -3663,7 +3939,8 @@
 +	}
 +}
 +
-+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},
@@ -3677,6 +3954,20 @@
 +	{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)
@@ -4694,24 +4985,69 @@
 +				     LWTBL_LEN_IN_DW, lwtbl);
 +
 +		if (lwtbl[4] || lwtbl[5] || lwtbl[6] || lwtbl[7] || lwtbl[0] || lwtbl[1]) {
-+			u32 *addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_2*4]);
-+			u32 dw_value = *addr;
++			u32 *addr, dw_value;
 +
 +			seq_printf(s, "wcid:%d\tAddr: %02x:%02x:%02x:%02x:%02x:%02x",
 +					i, lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]);
-+			seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW2[0].name,
++
++			addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_2*4]);
++			dw_value = *addr;
++			seq_printf(s, "\t%s:%u", WTBL_LMAC_DW2[0].name,
 +					(dw_value & WTBL_LMAC_DW2[0].mask) >> WTBL_LMAC_DW2[0].shift);
++
++			addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_5*4]);
++			dw_value = *addr;
++			seq_printf(s, "\tPSM:%u\n", !!(dw_value & WF_LWTBL_PSM_MASK));
 +		}
 +	}
 +
 +	return 0;
 +}
 +
++static int mt7996_token_read(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	int msdu_id;
++	struct mt76_txwi_cache *txwi;
++
++	seq_printf(s, "Token from host:\n");
++	spin_lock_bh(&dev->mt76.token_lock);
++	idr_for_each_entry(&dev->mt76.token, txwi, msdu_id) {
++		seq_printf(s, "%4d (pending time %u ms)\n", msdu_id,
++			   jiffies_to_msecs(jiffies - txwi->jiffies));
++	}
++	spin_unlock_bh(&dev->mt76.token_lock);
++	seq_printf(s, "\n");
++
++	return 0;
++}
++
 +int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
 +{
 +	struct mt7996_dev *dev = phy->dev;
++	u32 device_id = (dev->mt76.rev) >> 16;
++	int i = 0;
++	static const struct mt7996_dbg_reg_desc dbg_reg_s[] = {
++		{ 0x7990, mt7996_dbg_offs },
++		{ 0x7992, mt7992_dbg_offs },
++	};
 +
-+	mt7996_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);
++	for (i = 0; i < ARRAY_SIZE(dbg_reg_s); i++) {
++		if (device_id == dbg_reg_s[i].id) {
++			dev->dbg_reg = &dbg_reg_s[i];
++			break;
++		}
++	}
++
++	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;
++	}
 +
 +	/* agg */
 +	debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info0", dir,
@@ -4753,6 +5089,8 @@
 +	debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
 +				    mt7996_wtbl_read);
 +
++	debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, mt7996_token_read);
++
 +	debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable);
 +
 +	return 0;
@@ -4761,7 +5099,7 @@
 +#endif
 diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
 new file mode 100644
-index 0000000..e887016
+index 00000000..e8870166
 --- /dev/null
 +++ b/mt7996/mtk_mcu.c
 @@ -0,0 +1,18 @@
@@ -4785,7 +5123,7 @@
 +#endif
 diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
 new file mode 100644
-index 0000000..e741aa2
+index 00000000..e741aa27
 --- /dev/null
 +++ b/mt7996/mtk_mcu.h
 @@ -0,0 +1,16 @@
@@ -4806,7 +5144,7 @@
 +
 +#endif
 diff --git a/tools/fwlog.c b/tools/fwlog.c
-index e5d4a10..3c6a61d 100644
+index e5d4a105..3c6a61d7 100644
 --- a/tools/fwlog.c
 +++ b/tools/fwlog.c
 @@ -26,7 +26,7 @@ static const char *debugfs_path(const char *phyname, const char *file)
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-mtk-wifi-mt76-mt7996-support-record-muru-algo-log-wh.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-mtk-wifi-mt76-mt7996-support-record-muru-algo-log-wh.patch
new file mode 100644
index 0000000..f707328
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-mtk-wifi-mt76-mt7996-support-record-muru-algo-log-wh.patch
@@ -0,0 +1,144 @@
+From 80a3aa92334b91d0f6f0a8793a2e70391bcd1d12 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Tue, 28 Nov 2023 16:01:33 +0800
+Subject: [PATCH 1001/1041] mtk: wifi: mt76: mt7996: support record muru algo
+ log when record fw log
+
+Support record muru algorithm debug log in firmware when we use
+chihuahua tool to record fw log. This can help us to check some key
+point of muru algorithm result, like bsrp status, airtime busy status,
+ru candidate...
+Corresponding to Logan driver, it is the same as execute the iwpriv
+command: iwpriv rax0 set muruDbgInfo=[category]-1
+
+Disable muru debug log when we stop record fwlog. Without this commit,
+if we run $ echo 2 > fw_debug_wm after recording fwlog, it will print
+out too many fw debug log.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/debugfs.c | 35 +++++++++++++++++++++++++++++++++++
+ mt7996/mt7996.h  |  1 +
+ mt7996/mtk_mcu.c | 21 +++++++++++++++++++++
+ mt7996/mtk_mcu.h |  3 +++
+ 4 files changed, 60 insertions(+)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index c4b82cb2..f4ce3b55 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -423,6 +423,36 @@ remove_buf_file_cb(struct dentry *f)
+ 	return 0;
+ }
+ 
++static int
++mt7996_fw_debug_muru_set(void *data)
++{
++	struct mt7996_dev *dev = data;
++	enum {
++		DEBUG_BSRP_STATUS = 256,
++		DEBUG_TX_DATA_BYTE_CONUT,
++		DEBUG_RX_DATA_BYTE_CONUT,
++		DEBUG_RX_TOTAL_BYTE_CONUT,
++		DEBUG_INVALID_TID_BSR,
++		DEBUG_UL_LONG_TERM_PPDU_TYPE,
++		DEBUG_DL_LONG_TERM_PPDU_TYPE,
++		DEBUG_PPDU_CLASS_TRIG_ONOFF,
++		DEBUG_AIRTIME_BUSY_STATUS,
++		DEBUG_UL_OFDMA_MIMO_STATUS,
++		DEBUG_RU_CANDIDATE,
++		DEBUG_MEC_UPDATE_AMSDU,
++	} debug;
++	int ret;
++
++	for (debug = DEBUG_BSRP_STATUS; debug <= DEBUG_MEC_UPDATE_AMSDU; debug++) {
++		ret = mt7996_mcu_muru_dbg_info(dev, debug,
++					       dev->fw_debug_bin & BIT(0));
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
+ static int
+ mt7996_fw_debug_bin_set(void *data, u64 val)
+ {
+@@ -431,6 +461,7 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
+ 		.remove_buf_file = remove_buf_file_cb,
+ 	};
+ 	struct mt7996_dev *dev = data;
++	int ret;
+ 
+ 	if (!dev->relay_fwlog) {
+ 		dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir,
+@@ -443,6 +474,10 @@ mt7996_fw_debug_bin_set(void *data, u64 val)
+ 
+ 	relay_reset(dev->relay_fwlog);
+ 
++	ret = mt7996_fw_debug_muru_set(dev);
++	if (ret)
++		return ret;
++
+ 	return mt7996_fw_debug_wm_set(dev, dev->fw_debug_wm);
+ }
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 34159f97..29976860 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -677,6 +677,7 @@ 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);
++int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
+ #endif
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index e8870166..c16b25ab 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -15,4 +15,25 @@
+ 
+ 
+ 
++int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
++{
++	struct {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++
++		__le16 item;
++		u8 __rsv2[2];
++		__le32 value;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_MURU_DBG_INFO),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.item = cpu_to_le16(item),
++		.value = cpu_to_le32(val),
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
++				 sizeof(req), true);
++}
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index e741aa27..7f4d4e02 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -10,6 +10,9 @@
+ 
+ #ifdef CONFIG_MTK_DEBUG
+ 
++enum {
++	UNI_CMD_MURU_DBG_INFO = 0x18,
++};
+ 
+ #endif
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch
similarity index 66%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch
index ff8d7a8..e94c68d 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1001-wifi-mt76-mt7996-add-check-for-hostapd-config-he_ldp.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch
@@ -1,23 +1,24 @@
-From cb64d3c0b0dd79b8255caef614b13fe17f1b5b07 Mon Sep 17 00:00:00 2001
+From 9b07919cd131c27ae7507632a57767727815bbd9 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
+Subject: [PATCH 1002/1041] mtk: 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.
 
+Add check for STA LDPC cap, if STA only have BCC we should not overwrite the phy_cap with config he_ldpc.
+
 Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
-Change-Id: I6d6f59df8897e3c00f2e0a1e3c6e5701e31c5e4b
 ---
- mt7996/mcu.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
+ mt7996/mcu.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
 
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index fdc4fb4..7d0c511 100644
+index 3ecdde86..b379b226 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1096,7 +1096,8 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+@@ -1182,7 +1182,8 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
  }
  
  static void
@@ -27,18 +28,19 @@
  {
  	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)
+@@ -1202,6 +1203,11 @@ 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)
++	if (vif->type == NL80211_IFTYPE_AP &&
++	    (elem->phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
 +		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,
+@@ -2108,7 +2114,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  	 * update sta_rec_he here.
  	 */
  	if (changed)
@@ -47,7 +49,7 @@
  
  	/* 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,
+@@ -2194,7 +2200,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 */
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-mtk-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
similarity index 87%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-mtk-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
index 56f85a8..ee2c2c6 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1002-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-mtk-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
@@ -1,7 +1,8 @@
-From e622295e18a1af30c999928701787d8c562621c3 Mon Sep 17 00:00:00 2001
+From 7ff2021958001be2941953f6295c07cdcd7728e9 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 35/98] wifi: mt76: testmode: add atenl support in mt7996
+Subject: [PATCH 1003/1041] mtk: wifi: mt76: testmode: add atenl support in
+ mt7996
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
@@ -10,7 +11,7 @@
  2 files changed, 4 insertions(+), 1 deletion(-)
 
 diff --git a/testmode.c b/testmode.c
-index 4644dac..5c93aa6 100644
+index 4644dace..5c93aa6a 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -613,7 +613,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
@@ -24,7 +25,7 @@
  
  	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
 diff --git a/testmode.h b/testmode.h
-index 5e2792d..a40cd74 100644
+index 5e2792d8..a40cd74b 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -17,6 +17,7 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-wifi-mt76-testmode-add-basic-testmode-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-mtk-wifi-mt76-testmode-add-basic-testmode-support.patch
similarity index 80%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-wifi-mt76-testmode-add-basic-testmode-support.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-mtk-wifi-mt76-testmode-add-basic-testmode-support.patch
index 5b78a59..dc7d412 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1003-wifi-mt76-testmode-add-basic-testmode-support.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1004-mtk-wifi-mt76-testmode-add-basic-testmode-support.patch
@@ -1,37 +1,55 @@
-From ce58ffb18be834e2f62a30a71c9d6f5805517a9e Mon Sep 17 00:00:00 2001
+From 5ada52c4318533dafc3a77110ff161849508175c 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 36/98] wifi: mt76: testmode: add basic testmode support
+Subject: [PATCH 1004/1041] mtk: wifi: mt76: testmode: add basic testmode
+ support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Add testmode eeprom buffer mode support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Fix power & freq offset issue for iTest power cal & tx/rx verifcation
+1. Wait for fw to tx. Otherwise, iTest testing tool cannot get the
+accurate tx power.
+2. In crystal mode, freq offset is set in 6G band and forwarded to 5G
+and 2G band. Therefore, we should avoid reseting freq offset to 0 when
+6G interface is off.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+edcca return err in testmode; therefore, bypass it when we are in testmode idle state or testmode bf is on
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  eeprom.c          |   6 +-
  mac80211.c        |   3 +-
- mt76.h            |  35 +++
+ mt76.h            |  36 +++
  mt76_connac_mcu.h |   2 +
  mt7996/Makefile   |   1 +
  mt7996/eeprom.c   |  35 ++-
  mt7996/eeprom.h   |   1 +
  mt7996/init.c     |   8 +
  mt7996/mac.c      |   3 +-
- mt7996/main.c     |  16 ++
- mt7996/mcu.c      |  42 ++-
- mt7996/mcu.h      |  27 ++
- mt7996/mt7996.h   |  23 ++
- mt7996/testmode.c | 674 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/testmode.h | 297 ++++++++++++++++++++
- testmode.c        |  78 ++++--
- testmode.h        |  64 +++++
+ mt7996/main.c     |  26 ++
+ mt7996/mcu.c      |  59 +++-
+ mt7996/mcu.h      |  33 +++
+ mt7996/mt7996.h   |  28 +-
+ mt7996/testmode.c | 740 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/testmode.h | 299 +++++++++++++++++++
+ testmode.c        | 123 ++++++--
+ testmode.h        |  85 +++++-
  tools/fields.c    | 102 ++++++-
- 18 files changed, 1383 insertions(+), 34 deletions(-)
+ 18 files changed, 1542 insertions(+), 48 deletions(-)
  create mode 100644 mt7996/testmode.c
  create mode 100644 mt7996/testmode.h
 
 diff --git a/eeprom.c b/eeprom.c
-index a07ca84..437d8ca 100644
+index 7d5cf28f..85bd2a29 100644
 --- a/eeprom.c
 +++ b/eeprom.c
-@@ -94,8 +94,10 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs
+@@ -94,8 +94,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
  	}
  
  #ifdef CONFIG_NL80211_TESTMODE
@@ -45,10 +63,10 @@
  
  out_put_node:
 diff --git a/mac80211.c b/mac80211.c
-index cd102dd..f10ca90 100644
+index 6c5b4f55..d31cf9ff 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -835,7 +835,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
+@@ -846,7 +846,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
  	}
  
  #ifdef CONFIG_NL80211_TESTMODE
@@ -59,15 +77,16 @@
  		if (status->flag & RX_FLAG_FAILED_FCS_CRC)
  			phy->test.rx_stats.fcs_error[q]++;
 diff --git a/mt76.h b/mt76.h
-index 7f93210..feb861c 100644
+index de0021e4..7951b90e 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -692,14 +692,20 @@ struct mt76_testmode_ops {
+@@ -694,14 +694,21 @@ 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);
 +	void (*reset_rx_stats)(struct mt76_phy *phy);
 +	void (*tx_stop)(struct mt76_phy *phy);
++	int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
  };
  
 +#define MT_TM_FW_RX_COUNT	BIT(0)
@@ -83,7 +102,7 @@
  	u32 tx_count;
  	u16 tx_mpdu_len;
  
-@@ -709,6 +715,7 @@ struct mt76_testmode_data {
+@@ -711,6 +718,7 @@ struct mt76_testmode_data {
  	u8 tx_rate_sgi;
  	u8 tx_rate_ldpc;
  	u8 tx_rate_stbc;
@@ -91,7 +110,7 @@
  	u8 tx_ltf;
  
  	u8 tx_antenna_mask;
-@@ -718,6 +725,9 @@ struct mt76_testmode_data {
+@@ -720,6 +728,9 @@ struct mt76_testmode_data {
  	u32 tx_time;
  	u32 tx_ipg;
  
@@ -101,7 +120,7 @@
  	u32 freq_offset;
  
  	u8 tx_power[4];
-@@ -732,7 +742,16 @@ struct mt76_testmode_data {
+@@ -734,7 +745,16 @@ struct mt76_testmode_data {
  	struct {
  		u64 packets[__MT_RXQ_MAX];
  		u64 fcs_error[__MT_RXQ_MAX];
@@ -118,7 +137,7 @@
  };
  
  struct mt76_vif {
-@@ -1418,6 +1437,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1423,6 +1443,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);
  
@@ -142,10 +161,10 @@
  {
  #ifdef CONFIG_NL80211_TESTMODE
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index ca2e573..4d054bd 100644
+index 823b3626..0a55a4be 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1239,12 +1239,14 @@ enum {
+@@ -1255,12 +1255,14 @@ enum {
  	MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
  	MCU_UNI_CMD_RA = 0x2f,
  	MCU_UNI_CMD_MURU = 0x31,
@@ -161,7 +180,7 @@
  	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
  	MCU_UNI_CMD_PER_STA_INFO = 0x6d,
 diff --git a/mt7996/Makefile b/mt7996/Makefile
-index a056b40..7bb17f4 100644
+index a056b40e..7bb17f44 100644
 --- a/mt7996/Makefile
 +++ b/mt7996/Makefile
 @@ -8,5 +8,6 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
@@ -172,7 +191,7 @@
  
  mt7996e-y += mtk_debugfs.o mtk_mcu.o
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 7ae92e1..7fd318c 100644
+index 7d07c1b1..8fb1015e 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
 @@ -6,6 +6,11 @@
@@ -187,19 +206,17 @@
  
  static int mt7996_check_eeprom(struct mt7996_dev *dev)
  {
-@@ -23,7 +28,10 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+@@ -40,6 +45,9 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ 
  static char *mt7996_eeprom_name(struct mt7996_dev *dev)
  {
- 	/* reserve for future variants */
--	return MT7996_EEPROM_DEFAULT;
 +	if (dev->testmode_enable)
 +		return MT7996_EEPROM_DEFAULT_TM;
-+	else
-+		return MT7996_EEPROM_DEFAULT;
- }
- 
- static int
-@@ -52,21 +60,36 @@ out:
++
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
+ 		if (dev->chip_sku == MT7996_SKU_404)
+@@ -89,21 +97,36 @@ out:
  	return ret;
  }
  
@@ -241,8 +258,17 @@
  		ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);
  		if (ret < 0)
  			return ret;
+@@ -115,7 +138,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+ 		/* read eeprom data from efuse */
+ 		block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
+ 		for (i = 0; i < block_num; i++) {
+-			ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size);
++			ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
+ 			if (ret < 0)
+ 				return ret;
+ 		}
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 412d6e2..9ea3667 100644
+index 72c38ad3..de3ff4e2 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
 @@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
@@ -254,10 +280,10 @@
  	MT_EE_RATE_DELTA_2G =	0x1400,
  	MT_EE_RATE_DELTA_5G =	0x147d,
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 273d1e7..6d39c3c 100644
+index dae640e9..7bfebd38 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -800,6 +800,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -970,6 +970,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
  
  	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
  
@@ -268,7 +294,7 @@
  	ret = mt7996_mcu_init(dev);
  	if (ret)
  		return ret;
-@@ -1217,6 +1221,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1388,6 +1392,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
  
  	mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
  
@@ -280,7 +306,7 @@
  				   ARRAY_SIZE(mt76_rates));
  	if (ret)
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 32c52fc..637f0f6 100644
+index ce6759e0..924b05e4 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,
@@ -294,7 +320,7 @@
  
  	if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 0e51fe0..226235c 100644
+index 9fbd87d5..2a93e8c2 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -23,6 +23,18 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
@@ -325,7 +351,31 @@
  	mt7996_mac_enable_nf(dev, phy->mt76->band_idx);
  
  	ret = mt7996_mcu_set_rts_thresh(phy, 0x92b);
-@@ -1478,6 +1492,8 @@ const struct ieee80211_ops mt7996_ops = {
+@@ -291,6 +305,11 @@ int mt7996_set_channel(struct mt7996_phy *phy)
+ 
+ 	mt76_set_channel(phy->mt76);
+ 
++	if (mt76_testmode_enabled(phy->mt76) || phy->mt76->test.bf_en) {
++		mt7996_tm_update_channel(phy);
++		goto out;
++	}
++
+ 	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
+ 	if (ret)
+ 		goto out;
+@@ -398,6 +417,11 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
+ 	int ret;
+ 
+ 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
++		if (!mt76_testmode_enabled(phy->mt76) && !phy->mt76->test.bf_en) {
++			ret = mt7996_mcu_edcca_enable(phy, true);
++			if (ret)
++				return ret;
++		}
+ 		ieee80211_stop_queues(hw);
+ 		ret = mt7996_set_channel(phy);
+ 		if (ret)
+@@ -1507,6 +1531,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,
@@ -335,25 +385,64 @@
  	.sta_add_debugfs = mt7996_sta_add_debugfs,
  #endif
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 7d0c511..141b838 100644
+index b379b226..099ff74f 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -2681,8 +2681,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+@@ -2858,8 +2858,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
  {
  	int ret;
  
--	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 (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;
  
+@@ -3550,17 +3554,9 @@ int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
+ 				 &req, sizeof(req), true);
+ }
+ 
+-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
++int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
+ {
+-	struct {
+-		u8 _rsv[4];
+-
+-		__le16 tag;
+-		__le16 len;
+-		__le32 addr;
+-		__le32 valid;
+-		u8 data[16];
+-	} __packed req = {
++	struct mt7996_mcu_eeprom_info req = {
+ 		.tag = cpu_to_le16(UNI_EFUSE_ACCESS),
+ 		.len = cpu_to_le16(sizeof(req) - 4),
+ 		.addr = cpu_to_le32(round_down(offset,
+@@ -3569,6 +3565,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
+ 	struct sk_buff *skb;
+ 	bool valid;
+ 	int ret;
++	u8 *buf = read_buf;
+ 
+ 	ret = mt76_mcu_send_and_get_msg(&dev->mt76,
+ 					MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
+@@ -3579,7 +3576,9 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
+ 	valid = le32_to_cpu(*(__le32 *)(skb->data + 16));
+ 	if (valid) {
+ 		u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
+-		u8 *buf = (u8 *)dev->mt76.eeprom.data + addr;
++
++		if (!buf)
++			buf = (u8 *)dev->mt76.eeprom.data + addr;
+ 
-@@ -4308,3 +4312,37 @@ int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, bool auto_mode,
+ 		skb_pull(skb, 48);
+ 		memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
+@@ -4571,3 +4570,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);
  }
@@ -392,10 +481,27 @@
 +				 &req, sizeof(req), false);
 +}
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index ca16336..16ffc3d 100644
+index 238c4c53..325c3c97 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -814,6 +814,33 @@ enum {
+@@ -157,6 +157,16 @@ struct mt7996_mcu_eeprom {
+ 	__le16 buf_len;
+ } __packed;
+ 
++struct mt7996_mcu_eeprom_info {
++	u8 _rsv[4];
++
++	__le16 tag;
++	__le16 len;
++	__le32 addr;
++	__le32 valid;
++	u8 data[MT7996_EEPROM_BLOCK_SIZE];
++} __packed;
++
+ struct mt7996_mcu_phy_rx_info {
+ 	u8 category;
+ 	u8 rate;
+@@ -889,8 +899,31 @@ enum {
  	UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
  };
  
@@ -417,35 +523,52 @@
 +	u8 rsv[1];
 +} __packed;
 +
-+enum {
+ enum {
 +	UNI_TXPOWER_SKU_POWER_LIMIT_CTRL = 0,
 +	UNI_TXPOWER_PERCENTAGE_CTRL = 1,
 +	UNI_TXPOWER_PERCENTAGE_DROP_CTRL = 2,
 +	UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
-+	UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
+ 	UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
 +	UNI_TXPOWER_ATE_MODE_CTRL = 6,
-+};
-+
+ };
+ 
  enum {
- 	UNI_CMD_ACCESS_REG_BASIC = 0x0,
- 	UNI_CMD_ACCESS_RF_REG_BASIC,
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 8801956..3964035 100644
+index 29976860..5af55492 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -32,9 +32,11 @@
+@@ -32,25 +32,30 @@
  #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_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 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 MT7996_EEPROM_SIZE		7680
- #define MT7996_EEPROM_BLOCK_SIZE	16
- #define MT7996_TOKEN_SIZE		16384
-@@ -83,6 +85,7 @@ struct mt7996_dfs_pattern;
+ #define MT7992_EEPROM_DEFAULT		"mediatek/mt7996/mt7992_eeprom_2i5i.bin"
+ #define MT7992_EEPROM_DEFAULT_EXT	"mediatek/mt7996/mt7992_eeprom_2e5e.bin"
+ #define MT7992_EEPROM_DEFAULT_MIX	"mediatek/mt7996/mt7992_eeprom_2i5e.bin"
+@@ -126,6 +131,7 @@ enum mt7992_sku_type {
  
  enum mt7996_ram_type {
  	MT7996_RAM_TYPE_WM,
@@ -453,7 +576,7 @@
  	MT7996_RAM_TYPE_WA,
  	MT7996_RAM_TYPE_DSP,
  	__MT7996_RAM_TYPE_MAX,
-@@ -225,6 +228,21 @@ struct mt7996_phy {
+@@ -273,6 +279,21 @@ struct mt7996_phy {
  	struct mt76_channel_state state_ts;
  
  	bool has_aux_rx;
@@ -475,8 +598,8 @@
  };
  
  struct mt7996_dev {
-@@ -300,6 +318,8 @@ struct mt7996_dev {
- 		} session;
+@@ -353,6 +374,8 @@ struct mt7996_dev {
+ 		spinlock_t lock;
  	} wed_rro;
  
 +	bool testmode_enable;
@@ -484,7 +607,7 @@
  	bool ibf;
  	u8 fw_debug_wm;
  	u8 fw_debug_wa;
-@@ -414,6 +434,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
+@@ -467,6 +490,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;
@@ -492,7 +615,7 @@
  
  struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
  				     void __iomem *mem_base, u32 device_id);
-@@ -423,6 +444,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+@@ -476,6 +500,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);
@@ -500,20 +623,29 @@
  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);
-@@ -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);
+@@ -528,7 +553,7 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
+ 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_eeprom(struct mt7996_dev *dev);
+-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset);
++int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf);
+ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
+ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
+ int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
+@@ -563,6 +588,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_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
 +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..fb041c3
+index 00000000..96079c22
 --- /dev/null
 +++ b/mt7996/testmode.c
-@@ -0,0 +1,674 @@
+@@ -0,0 +1,740 @@
 +// SPDX-License-Identifier: ISC
 +/*
 + * Copyright (C) 2022 MediaTek Inc.
@@ -620,9 +752,10 @@
 +			.op.rf.param.func_data = cpu_to_le32(data),
 +		},
 +	};
++	bool wait = (data == RF_CMD(START_TX)) ? true : false;
 +
 +	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), &req,
-+				 sizeof(req), false);
++				 sizeof(req), wait);
 +}
 +
 +static int
@@ -917,10 +1050,11 @@
 +{
 +	struct mt76_testmode_data *td = &phy->mt76->test;
 +	struct mt7996_dev *dev = phy->dev;
-+	bool en = td->state != MT76_TM_STATE_OFF;
 +
-+	if (changed & BIT(TM_CHANGED_FREQ_OFFSET))
-+		mt7996_tm_set(dev, SET_ID(FREQ_OFFSET), en ? td->freq_offset : 0);
++	if (changed & BIT(TM_CHANGED_FREQ_OFFSET)) {
++		mt7996_tm_set(dev, SET_ID(FREQ_OFFSET), td->freq_offset);
++		mt7996_tm_set(dev, SET_ID(FREQ_OFFSET_C2), td->freq_offset);
++	}
 +	if (changed & BIT(TM_CHANGED_TXPOWER))
 +		mt7996_tm_set(dev, SET_ID(POWER), td->tx_power[0]);
 +	if (changed & BIT(TM_CHANGED_SKU_EN)) {
@@ -1181,19 +1315,83 @@
 +	return 0;
 +}
 +
++static int
++mt7996_tm_write_back_to_efuse(struct mt7996_dev *dev)
++{
++	struct mt7996_mcu_eeprom_info req = {
++		.tag = cpu_to_le16(UNI_EFUSE_ACCESS),
++		.len = cpu_to_le16(sizeof(req) - 4),
++	};
++	u8 read_buf[MT76_TM_EEPROM_BLOCK_SIZE], *eeprom = dev->mt76.eeprom.data;
++	int i, ret = -EINVAL;
++
++	/* prevent from damaging chip id in efuse */
++	if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
++		goto out;
++
++	for (i = 0; i < MT7996_EEPROM_SIZE; i += MT76_TM_EEPROM_BLOCK_SIZE) {
++		req.addr = cpu_to_le32(i);
++		memcpy(req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
++
++		ret = mt7996_mcu_get_eeprom(dev, i, read_buf);
++		if (ret < 0)
++			return ret;
++
++		if (!memcmp(req.data, read_buf, MT76_TM_EEPROM_BLOCK_SIZE))
++			continue;
++
++		ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
++					&req, sizeof(req), true);
++		if (ret)
++			return ret;
++	}
++
++out:
++	return ret;
++}
++
++static int
++mt7996_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
++{
++	struct mt7996_phy *phy = mphy->priv;
++	struct mt7996_dev *dev = phy->dev;
++	u8 *eeprom = dev->mt76.eeprom.data;
++	int ret = 0;
++
++	if (offset >= MT7996_EEPROM_SIZE)
++		return -EINVAL;
++
++	switch (action) {
++	case MT76_TM_EEPROM_ACTION_UPDATE_DATA:
++		memcpy(eeprom + offset, val, MT76_TM_EEPROM_BLOCK_SIZE);
++		break;
++	case MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE:
++		ret = mt7996_mcu_set_eeprom(dev);
++		break;
++	case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
++		ret = mt7996_tm_write_back_to_efuse(dev);
++		break;
++	default:
++		break;
++	}
++
++	return ret;
++}
++
 +const struct mt76_testmode_ops mt7996_testmode_ops = {
 +	.set_state = mt7996_tm_set_state,
 +	.set_params = mt7996_tm_set_params,
 +	.dump_stats = mt7996_tm_dump_stats,
 +	.reset_rx_stats = mt7996_tm_reset_trx_stats,
 +	.tx_stop = mt7996_tm_tx_stop,
++	.set_eeprom = mt7996_tm_set_eeprom,
 +};
 diff --git a/mt7996/testmode.h b/mt7996/testmode.h
 new file mode 100644
-index 0000000..e4d55a6
+index 00000000..319ef257
 --- /dev/null
 +++ b/mt7996/testmode.h
-@@ -0,0 +1,297 @@
+@@ -0,0 +1,299 @@
 +/* SPDX-License-Identifier: ISC */
 +/* Copyright (C) 2020 MediaTek Inc. */
 +
@@ -1343,6 +1541,8 @@
 +	RF_TEST_ID_SET_RX_MU_AID = 157,
 +	RF_TEST_ID_SET_HW_TX_MODE = 167,
 +	RF_TEST_ID_SET_PUNCTURE = 168,
++	RF_TEST_ID_SET_FREQ_OFFSET_C2 = 171,
++	RF_TEST_ID_GET_FREQ_OFFSET_C2 = 172,
 +	RF_TEST_ID_SET_CFG_ON = 176,
 +	RF_TEST_ID_SET_CFG_OFF = 177,
 +	RF_TEST_ID_SET_BSSID = 189,
@@ -1492,7 +1692,7 @@
 +
 +#endif
 diff --git a/testmode.c b/testmode.c
-index 5c93aa6..bbe8230 100644
+index 5c93aa6a..db2cc255 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -2,11 +2,13 @@
@@ -1609,7 +1809,64 @@
  	}
  
  	phy->test.state = state;
-@@ -434,6 +447,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -404,6 +417,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
+ 	return 0;
+ }
+ 
++static int
++mt76_testmode_set_eeprom(struct mt76_phy *phy, struct nlattr **tb)
++{
++	struct mt76_dev *dev = phy->dev;
++	u8 action, val[MT76_TM_EEPROM_BLOCK_SIZE];
++	u32 offset = 0;
++	int err = -EINVAL;
++
++	if (!dev->test_ops->set_eeprom)
++		return -EOPNOTSUPP;
++
++	if (mt76_tm_get_u8(tb[MT76_TM_ATTR_EEPROM_ACTION], &action,
++			   0, MT76_TM_EEPROM_ACTION_MAX))
++		goto out;
++
++	if (tb[MT76_TM_ATTR_EEPROM_OFFSET]) {
++		struct nlattr *cur;
++		int rem, idx = 0;
++
++		offset = nla_get_u32(tb[MT76_TM_ATTR_EEPROM_OFFSET]);
++		if (!!(offset % MT76_TM_EEPROM_BLOCK_SIZE) ||
++		    !tb[MT76_TM_ATTR_EEPROM_VAL])
++			goto out;
++
++		nla_for_each_nested(cur, tb[MT76_TM_ATTR_EEPROM_VAL], rem) {
++			if (nla_len(cur) != 1 || idx >= ARRAY_SIZE(val))
++				goto out;
++
++			val[idx++] = nla_get_u8(cur);
++		}
++	}
++
++	err = dev->test_ops->set_eeprom(phy, offset, val, action);
++
++out:
++	return err;
++}
++
+ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		      void *data, int len)
+ {
+@@ -427,6 +478,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 
+ 	mutex_lock(&dev->mutex);
+ 
++	if (tb[MT76_TM_ATTR_EEPROM_ACTION]) {
++		err = mt76_testmode_set_eeprom(phy, tb);
++		goto out;
++	}
++
+ 	if (tb[MT76_TM_ATTR_RESET]) {
+ 		mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
+ 		memset(td, 0, sizeof(*td));
+@@ -434,6 +490,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  
  	mt76_testmode_init_defaults(phy);
  
@@ -1619,7 +1876,7 @@
  	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,
+@@ -454,7 +513,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],
@@ -1629,7 +1886,7 @@
  		goto out;
  
  	if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -494,7 +511,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -494,7 +554,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  			    idx >= ARRAY_SIZE(td->tx_power))
  				goto out;
  
@@ -1640,7 +1897,7 @@
  		}
  	}
  
-@@ -512,6 +531,22 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -512,6 +574,22 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  		}
  	}
  
@@ -1663,7 +1920,7 @@
  	if (dev->test_ops->set_params) {
  		err = dev->test_ops->set_params(phy, tb, state);
  		if (err)
-@@ -561,6 +596,9 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
+@@ -561,6 +639,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,
@@ -1673,7 +1930,7 @@
  			      MT76_TM_STATS_ATTR_PAD))
  		return -EMSGSIZE;
  
-@@ -625,6 +663,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -625,6 +706,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) ||
@@ -1682,11 +1939,30 @@
  	    (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) &&
+@@ -640,7 +723,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
+ 	     nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&
+-	     nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
++	     nla_put_u32(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
+ 		goto out;
+ 
+ 	if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
 diff --git a/testmode.h b/testmode.h
-index a40cd74..141bb86 100644
+index a40cd74b..96872e8c 100644
 --- a/testmode.h
 +++ b/testmode.h
-@@ -19,6 +19,7 @@
+@@ -5,7 +5,8 @@
+ #ifndef __MT76_TESTMODE_H
+ #define __MT76_TESTMODE_H
+ 
+-#define MT76_TM_TIMEOUT	10
++#define MT76_TM_TIMEOUT			10
++#define MT76_TM_EEPROM_BLOCK_SIZE	16
+ 
+ /**
+  * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
+@@ -19,6 +20,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)
   *
@@ -1694,7 +1970,7 @@
   * @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 @@
+@@ -39,6 +41,11 @@
   *
   * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
   *
@@ -1706,7 +1982,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 +54,29 @@
+@@ -48,6 +55,29 @@
   * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
   *
   * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
@@ -1736,7 +2012,7 @@
   */
  enum mt76_testmode_attr {
  	MT76_TM_ATTR_UNSPEC,
-@@ -59,6 +88,7 @@ enum mt76_testmode_attr {
+@@ -59,6 +89,7 @@ enum mt76_testmode_attr {
  	MT76_TM_ATTR_MTD_OFFSET,
  	MT76_TM_ATTR_BAND_IDX,
  
@@ -1744,7 +2020,7 @@
  	MT76_TM_ATTR_TX_COUNT,
  	MT76_TM_ATTR_TX_LENGTH,
  	MT76_TM_ATTR_TX_RATE_MODE,
-@@ -76,6 +106,8 @@ enum mt76_testmode_attr {
+@@ -76,6 +107,8 @@ enum mt76_testmode_attr {
  	MT76_TM_ATTR_FREQ_OFFSET,
  
  	MT76_TM_ATTR_STATS,
@@ -1753,7 +2029,7 @@
  
  	MT76_TM_ATTR_TX_SPE_IDX,
  
-@@ -86,6 +118,27 @@ enum mt76_testmode_attr {
+@@ -86,6 +119,27 @@ enum mt76_testmode_attr {
  	MT76_TM_ATTR_DRV_DATA,
  
  	MT76_TM_ATTR_MAC_ADDRS,
@@ -1781,7 +2057,7 @@
  
  	/* keep last */
  	NUM_MT76_TM_ATTRS,
-@@ -103,6 +156,8 @@ enum mt76_testmode_attr {
+@@ -103,6 +157,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
@@ -1790,7 +2066,7 @@
   */
  enum mt76_testmode_stats_attr {
  	MT76_TM_STATS_ATTR_UNSPEC,
-@@ -115,6 +170,7 @@ enum mt76_testmode_stats_attr {
+@@ -115,6 +171,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,
@@ -1798,7 +2074,7 @@
  
  	/* keep last */
  	NUM_MT76_TM_STATS_ATTRS,
-@@ -127,6 +183,7 @@ enum mt76_testmode_stats_attr {
+@@ -127,6 +184,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)
@@ -1806,7 +2082,7 @@
   * @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 {
+@@ -136,6 +194,7 @@ enum mt76_testmode_rx_attr {
  
  	MT76_TM_RX_ATTR_FREQ_OFFSET,
  	MT76_TM_RX_ATTR_RCPI,
@@ -1814,7 +2090,7 @@
  	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 {
+@@ -179,6 +238,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
@@ -1824,7 +2100,7 @@
   */
  enum mt76_testmode_tx_mode {
  	MT76_TM_TX_MODE_CCK,
-@@ -189,6 +250,9 @@ enum mt76_testmode_tx_mode {
+@@ -189,12 +251,33 @@ enum mt76_testmode_tx_mode {
  	MT76_TM_TX_MODE_HE_EXT_SU,
  	MT76_TM_TX_MODE_HE_TB,
  	MT76_TM_TX_MODE_HE_MU,
@@ -1834,8 +2110,32 @@
  
  	/* keep last */
  	NUM_MT76_TM_TX_MODES,
+ 	MT76_TM_TX_MODE_MAX = NUM_MT76_TM_TX_MODES - 1,
+ };
+ 
++/**
++ * enum mt76_testmode_eeprom_action - eeprom setting actions
++ *
++ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
++ *	eeprom data block
++ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
++ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
++ */
++enum mt76_testmode_eeprom_action {
++	MT76_TM_EEPROM_ACTION_UPDATE_DATA,
++	MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
++	MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
++
++	/* keep last */
++	NUM_MT76_TM_EEPROM_ACTION,
++	MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
++};
++
+ extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
+ 
+ #endif
 diff --git a/tools/fields.c b/tools/fields.c
-index e3f6908..055f90f 100644
+index e3f69089..055f90f3 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch
similarity index 92%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch
index 1185d02..e1e2ecc 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch
@@ -1,11 +1,10 @@
-From db3b9fa4bc9c70231b7237dee2f7bcf35c6135f2 Mon Sep 17 00:00:00 2001
+From 52b8f9d42643b5103fc608fb1848e03eac88834c 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 43/98] wifi: mt76: testmode: add testmode pre-calibration
- support
+Subject: [PATCH 1005/1041] mtk: wifi: mt76: testmode: add testmode
+ pre-calibration support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Change-Id: If8a6cc02fa20e35f079c826e0571e8c04c3f9c7e
 ---
  mac80211.c        |  21 ---
  mt76.h            |  22 +++
@@ -22,7 +21,7 @@
  12 files changed, 632 insertions(+), 23 deletions(-)
 
 diff --git a/mac80211.c b/mac80211.c
-index f10ca90..9c582cb 100644
+index d31cf9ff..87dcc8a3 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -7,27 +7,6 @@
@@ -54,7 +53,7 @@
  	CHAN2G(1, 2412),
  	CHAN2G(2, 2417),
 diff --git a/mt76.h b/mt76.h
-index feb861c..fc69d3e 100644
+index 7951b90e..b0897ac2 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -18,6 +18,27 @@
@@ -85,19 +84,19 @@
  #define MT_MCU_RING_SIZE	32
  #define MT_RX_BUF_SIZE		2048
  #define MT_SKB_HEAD_LEN		256
-@@ -694,6 +715,7 @@ struct mt76_testmode_ops {
- 	int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
+@@ -697,6 +718,7 @@ struct mt76_testmode_ops {
  	void (*reset_rx_stats)(struct mt76_phy *phy);
  	void (*tx_stop)(struct mt76_phy *phy);
+ 	int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
 +	int (*dump_precal)(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type);
  };
  
  #define MT_TM_FW_RX_COUNT	BIT(0)
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index bbf600b..d65ecf0 100644
+index 0a55a4be..3447f523 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1023,8 +1023,10 @@ enum {
+@@ -1031,8 +1031,10 @@ enum {
  	MCU_UNI_EVENT_RDD_REPORT = 0x11,
  	MCU_UNI_EVENT_ROC = 0x27,
  	MCU_UNI_EVENT_TX_DONE = 0x2d,
@@ -105,11 +104,11 @@
  	MCU_UNI_EVENT_THERMAL = 0x35,
  	MCU_UNI_EVENT_NIC_CAPAB = 0x43,
 +	MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
+ 	MCU_UNI_EVENT_WED_RRO = 0x57,
  	MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
  	MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
- };
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index e4c4b86..b88fd64 100644
+index 8fb1015e..29a245ce 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
 @@ -12,6 +12,42 @@ static bool testmode_enable;
@@ -154,9 +153,9 @@
 +
  static int mt7996_check_eeprom(struct mt7996_dev *dev)
  {
- 	u8 *eeprom = dev->mt76.eeprom.data;
-@@ -36,6 +72,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
- 		return MT7996_EEPROM_DEFAULT;
+ #define FEM_INT				0
+@@ -71,6 +107,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ 	}
  }
  
 +int
@@ -193,7 +192,7 @@
  mt7996_eeprom_load_default(struct mt7996_dev *dev)
  {
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 343e65e..7ff290f 100644
+index de3ff4e2..849b8bca 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
 @@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
@@ -204,9 +203,9 @@
  	MT_EE_TESTMODE_EN =	0x1af,
  	MT_EE_MAC_ADDR3 =	0x2c0,
  	MT_EE_RATE_DELTA_2G =	0x1400,
-@@ -31,6 +32,52 @@ enum mt7996_eeprom_field {
- #define MT_EE_WIFI_CONF1_BAND_SEL		GENMASK(5, 3)
+@@ -32,6 +33,52 @@ enum mt7996_eeprom_field {
  #define MT_EE_WIFI_CONF2_BAND_SEL		GENMASK(2, 0)
+ #define MT_EE_WIFI_PA_LNA_CONFIG		GENMASK(1, 0)
  
 +#define MT_EE_WIFI_CAL_GROUP_2G			BIT(0)
 +#define MT_EE_WIFI_CAL_GROUP_5G			BIT(1)
@@ -258,12 +257,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 a008c08..d6f4e22 100644
+index 099ff74f..eb346a9c 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -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);
+@@ -712,6 +712,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	case MCU_UNI_EVENT_WED_RRO:
+ 		mt7996_mcu_wed_rro_event(dev, skb);
  		break;
 +#ifdef CONFIG_NL80211_TESTMODE
 +	case MCU_UNI_EVENT_TESTMODE_CTRL:
@@ -274,7 +273,7 @@
  		break;
  	}
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 3c535be..684c254 100644
+index 5af55492..e7609c63 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
 @@ -385,6 +385,9 @@ struct mt7996_dev {
@@ -285,9 +284,9 @@
 +	u32 cur_prek_offset;
 +
  	struct {
- 		u8 table_mask;
+ 		u16 table_mask;
  		u8 n_agrt;
-@@ -521,6 +524,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
+@@ -505,6 +508,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);
@@ -295,10 +294,10 @@
  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);
-@@ -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);
+@@ -589,6 +593,9 @@ void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
+ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
 +#ifdef CONFIG_NL80211_TESTMODE
 +void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
 +#endif
@@ -306,7 +305,7 @@
  static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
  {
 diff --git a/mt7996/testmode.c b/mt7996/testmode.c
-index fb041c3..8ceea00 100644
+index 96079c22..36be0ff8 100644
 --- a/mt7996/testmode.c
 +++ b/mt7996/testmode.c
 @@ -7,6 +7,8 @@
@@ -318,7 +317,7 @@
  
  enum {
  	TM_CHANGED_TXPOWER,
-@@ -396,6 +398,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
+@@ -397,6 +399,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
  	}
  }
  
@@ -755,7 +754,7 @@
  static void
  mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
  {
-@@ -452,6 +884,10 @@ mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -454,6 +886,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));
@@ -766,14 +765,14 @@
  
  	if ((state == MT76_TM_STATE_IDLE &&
  	     prev_state == MT76_TM_STATE_OFF) ||
-@@ -671,4 +1107,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
- 	.dump_stats = mt7996_tm_dump_stats,
+@@ -737,4 +1173,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
  	.reset_rx_stats = mt7996_tm_reset_trx_stats,
  	.tx_stop = mt7996_tm_tx_stop,
+ 	.set_eeprom = mt7996_tm_set_eeprom,
 +	.dump_precal = mt7996_tm_dump_precal,
  };
 diff --git a/mt7996/testmode.h b/mt7996/testmode.h
-index e4d55a6..17c1456 100644
+index 319ef257..9bfb86f2 100644
 --- a/mt7996/testmode.h
 +++ b/mt7996/testmode.h
 @@ -34,6 +34,12 @@ enum bw_mapping_method {
@@ -835,10 +834,10 @@
  	RF_OPER_NORMAL,
  	RF_OPER_RF_TEST,
 diff --git a/testmode.c b/testmode.c
-index bbe8230..e66b54a 100644
+index db2cc255..7ed58a77 100644
 --- a/testmode.c
 +++ b/testmode.c
-@@ -631,6 +631,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -674,6 +674,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
  
  	mutex_lock(&dev->mutex);
  
@@ -858,10 +857,10 @@
  		err = -EINVAL;
  
 diff --git a/testmode.h b/testmode.h
-index 141bb86..db8ff53 100644
+index 96872e8c..d6601cdc 100644
 --- a/testmode.h
 +++ b/testmode.h
-@@ -219,6 +219,14 @@ enum mt76_testmode_state {
+@@ -220,6 +220,14 @@ enum mt76_testmode_state {
  	MT76_TM_STATE_TX_FRAMES,
  	MT76_TM_STATE_RX_FRAMES,
  	MT76_TM_STATE_TX_CONT,
@@ -877,7 +876,7 @@
  
  	/* keep last */
 diff --git a/tools/fields.c b/tools/fields.c
-index 055f90f..b012276 100644
+index 055f90f3..b0122763 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch
similarity index 60%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch
index 78ae8ad..90ff7e8 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1005-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch
@@ -1,27 +1,29 @@
-From b02a81b168e9c42350c1f6a9b7e38c60c76cc692 Mon Sep 17 00:00:00 2001
+From d96436bbd8f0aa903bb0ee905a2654f81ebbfbff 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 38/98] wifi: mt76: mt7996: enable SCS feature for mt7996
- driver
+Subject: [PATCH 1006/1041] mtk: wifi: mt76: mt7996: enable SCS feature for
+ mt7996 driver
 
 Enable Smart Carrier Sense algorithn by default to improve performance
 in a noisy environment.
 
 Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
 ---
- mt76_connac_mcu.h |   1 +
- mt7996/init.c     |   1 +
- mt7996/main.c     |   7 +++
- mt7996/mcu.c      | 123 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.h      |   6 +++
- mt7996/mt7996.h   |  15 ++++++
- 6 files changed, 153 insertions(+)
+ mt76_connac_mcu.h    |   1 +
+ mt7996/init.c        |   1 +
+ mt7996/mac.c         |   2 +
+ mt7996/main.c        |   7 +++
+ mt7996/mcu.c         | 105 +++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h         |   6 +++
+ mt7996/mt7996.h      |  15 +++++++
+ mt7996/mtk_debugfs.c |  11 +++++
+ 8 files changed, 148 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 4d054bd..fae76c9 100644
+index 3447f523..5e1b15c4 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1232,6 +1232,7 @@ enum {
+@@ -1250,6 +1250,7 @@ enum {
  	MCU_UNI_CMD_GET_STAT_INFO = 0x23,
  	MCU_UNI_CMD_SNIFFER = 0x24,
  	MCU_UNI_CMD_SR = 0x25,
@@ -30,10 +32,10 @@
  	MCU_UNI_CMD_SET_DBDC_PARMS = 0x28,
  	MCU_UNI_CMD_TXPOWER = 0x2b,
 diff --git a/mt7996/init.c b/mt7996/init.c
-index fed74d0..f393e04 100644
+index 7bfebd38..c9c7c20a 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -1211,6 +1211,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1378,6 +1378,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);
@@ -41,8 +43,28 @@
  	INIT_LIST_HEAD(&dev->sta_rc_list);
  	INIT_LIST_HEAD(&dev->twt_list);
  
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 924b05e4..e307ddc3 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1798,6 +1798,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ 		cancel_delayed_work_sync(&phy2->mt76->mac_work);
+ 	if (phy3)
+ 		cancel_delayed_work_sync(&phy3->mt76->mac_work);
++	cancel_delayed_work_sync(&dev->scs_work);
+ 
+ 	mutex_lock(&dev->mt76.mutex);
+ 	for (i = 0; i < 10; i++) {
+@@ -1833,6 +1834,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ 		ieee80211_queue_delayed_work(phy3->mt76->hw,
+ 					     &phy3->mt76->mac_work,
+ 					     MT7996_WATCHDOG_TIME);
++	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
+ }
+ 
+ void mt7996_mac_reset_work(struct work_struct *work)
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 226235c..6fa4a65 100644
+index 2a93e8c2..97f1ef8c 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -73,11 +73,17 @@ int mt7996_run(struct ieee80211_hw *hw)
@@ -72,10 +94,10 @@
  	mutex_lock(&dev->mt76.mutex);
  
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 141b838..6cedc39 100644
+index eb346a9c..cc417039 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -4346,3 +4346,126 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+@@ -4609,3 +4609,108 @@ 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);
  }
@@ -108,27 +130,7 @@
 +void mt7996_sta_rssi_work(void *data, struct ieee80211_sta *sta)
 +{
 +	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-+	struct mt7996_dev *dev = (struct mt7996_dev *)data;
-+	struct mt7996_phy *poll_phy;
-+	u8 band_idx = msta->wcid.phy_idx;
-+
-+	switch (band_idx) {
-+	case MT_BAND0:
-+		poll_phy = dev->mphy.priv;
-+		break;
-+	case MT_BAND1:
-+		poll_phy = mt7996_phy2(dev);
-+		break;
-+	case MT_BAND2:
-+		poll_phy = mt7996_phy3(dev);
-+		break;
-+	default:
-+		poll_phy = NULL;
-+		break;
-+	}
-+
-+	if (!poll_phy->scs_ctrl.scs_enable)
-+		return;
++	struct mt7996_phy *poll_phy = (struct mt7996_phy *) data;
 +
 +	if (poll_phy->scs_ctrl.sta_min_rssi > msta->ack_signal)
 +		poll_phy->scs_ctrl.sta_min_rssi = msta->ack_signal;
@@ -141,8 +143,6 @@
 +	bool scs_enable_flag = false;
 +	u8 i;
 +
-+	ieee80211_iterate_stations_atomic(dev->mphy.hw, mt7996_sta_rssi_work, dev);
-+
 +	for (i = 0; i < __MT_MAX_BAND; i++) {
 +		struct mt7996_phy *phy;
 +
@@ -161,13 +161,17 @@
 +			break;
 +		}
 +
-+		if (phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state) &&
-+		    phy->scs_ctrl.scs_enable) {
-+			scs_enable_flag = true;
-+			if (mt7996_mcu_set_scs_stats(phy))
-+				dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n");
-+			phy->scs_ctrl.sta_min_rssi = 0;
-+		}
++		if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state) ||
++		    !phy->scs_ctrl.scs_enable)
++			continue;
++
++		ieee80211_iterate_stations_atomic(phy->mt76->hw,
++						  mt7996_sta_rssi_work, phy);
++
++		scs_enable_flag = true;
++		if (mt7996_mcu_set_scs_stats(phy))
++			dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n");
++		phy->scs_ctrl.sta_min_rssi = 0;
 +	}
 +
 +	if (scs_enable_flag)
@@ -203,10 +207,10 @@
 +				 &req, sizeof(req), false);
 +}
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 16ffc3d..ff9cc9c 100644
+index 325c3c97..4f4994d8 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -875,6 +875,12 @@ enum {
+@@ -960,6 +960,12 @@ enum {
  	UNI_CMD_PP_EN_CTRL,
  };
  
@@ -220,10 +224,10 @@
  #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 efdcff7..eb48dbd 100644
+index e7609c63..384157c8 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -193,6 +193,16 @@ struct mt7996_hif {
+@@ -233,6 +233,16 @@ struct mt7996_hif {
  	int irq;
  };
  
@@ -240,7 +244,7 @@
  struct mt7996_wed_rro_addr {
  	u32 head_low;
  	u32 head_high : 4;
-@@ -235,6 +245,8 @@ struct mt7996_phy {
+@@ -280,6 +290,8 @@ struct mt7996_phy {
  
  	bool has_aux_rx;
  
@@ -249,7 +253,7 @@
  #ifdef CONFIG_NL80211_TESTMODE
  	struct {
  		u32 *reg_backup;
-@@ -280,6 +292,7 @@ struct mt7996_dev {
+@@ -326,6 +338,7 @@ struct mt7996_dev {
  	struct work_struct rc_work;
  	struct work_struct dump_work;
  	struct work_struct reset_work;
@@ -257,15 +261,44 @@
  	wait_queue_head_t reset_wait;
  	struct {
  		u32 state;
-@@ -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);
+@@ -596,6 +609,8 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ #ifdef CONFIG_NL80211_TESTMODE
+ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
 +int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
 +void mt7996_mcu_scs_sta_poll(struct work_struct *work);
  
  static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
  {
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 53b11d54..ccb147e9 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2407,6 +2407,16 @@ static int mt7996_token_read(struct seq_file *s, void *data)
+ 	return 0;
+ }
+ 
++static int
++mt7996_scs_enable_set(void *data, u64 val)
++{
++	struct mt7996_phy *phy = data;
++
++	return mt7996_mcu_set_scs(phy, (u8) val);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL,
++			 mt7996_scs_enable_set, "%lld\n");
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2477,6 +2487,7 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, mt7996_token_read);
+ 
+ 	debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable);
++	debugfs_create_file("scs_enable", 0200, dir, phy, &fops_scs_enable);
+ 
+ 	return 0;
+ }
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-wifi-mt76-mt7996-add-txpower-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-mtk-wifi-mt76-mt7996-add-txpower-support.patch
similarity index 91%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-wifi-mt76-mt7996-add-txpower-support.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-mtk-wifi-mt76-mt7996-add-txpower-support.patch
index 0a0d376..8244fc7 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1006-wifi-mt76-mt7996-add-txpower-support.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-mtk-wifi-mt76-mt7996-add-txpower-support.patch
@@ -1,26 +1,25 @@
-From 1c1dd57bde8919fdf04ef914b781eb6183582562 Mon Sep 17 00:00:00 2001
+From f656a23959ac8662dbb38b079a7afd440367578c 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 39/98] wifi: mt76: mt7996: add txpower support
+Subject: [PATCH 1007/1041] mtk: wifi: mt76: mt7996: add txpower support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Change-Id: Ic3e7b17f3664fa7f774137572f885359fa2ec93b
 ---
  mt7996/eeprom.c      |  34 +++++++
  mt7996/eeprom.h      |  42 ++++++++
  mt7996/mcu.h         |   2 +
- mt7996/mt7996.h      |   3 +
+ mt7996/mt7996.h      |   1 +
  mt7996/mtk_debugfs.c | 229 +++++++++++++++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.c     |  23 +++++
- mt7996/mtk_mcu.h     |  78 +++++++++++++++
+ mt7996/mtk_mcu.h     |  79 +++++++++++++++
  mt7996/regs.h        |  29 +++---
- 8 files changed, 429 insertions(+), 11 deletions(-)
+ 8 files changed, 428 insertions(+), 11 deletions(-)
 
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 3276740..e4c4b86 100644
+index 29a245ce..6c1966b7 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
-@@ -296,3 +296,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
+@@ -401,3 +401,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
  
  	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
  }
@@ -59,10 +58,10 @@
 +	[SKU_EHT3x996_484] = 16,
 +};
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 9ea3667..343e65e 100644
+index 849b8bca..23d4929d 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
-@@ -75,4 +75,46 @@ mt7996_get_channel_group_6g(int channel)
+@@ -123,4 +123,46 @@ mt7996_get_channel_group_6g(int channel)
  	return DIV_ROUND_UP(channel - 29, 32);
  }
  
@@ -110,10 +109,10 @@
 +
  #endif
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index ff9cc9c..71dc165 100644
+index 4f4994d8..887d9b49 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -826,6 +826,7 @@ struct tx_power_ctrl {
+@@ -911,6 +911,7 @@ struct tx_power_ctrl {
  		bool ate_mode_enable;
  		bool percentage_ctrl_enable;
  		bool bf_backoff_enable;
@@ -121,7 +120,7 @@
  		u8 power_drop_level;
  	};
  	u8 band_idx;
-@@ -839,6 +840,7 @@ enum {
+@@ -924,6 +925,7 @@ enum {
  	UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
  	UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
  	UNI_TXPOWER_ATE_MODE_CTRL = 6,
@@ -130,33 +129,24 @@
  
  enum {
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index eb48dbd..23d1614 100644
+index 384157c8..18a6a46d 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -63,6 +63,8 @@
- 
- #define MT7996_BUILD_TIME_LEN		24
- 
-+#define MT7996_SKU_RATE_NUM		417
-+
- #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);
+@@ -609,6 +609,7 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ #ifdef CONFIG_NL80211_TESTMODE
+ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
 +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 5aa5c94..57fcbab 100644
+index ccb147e9..93428851 100644
 --- a/mt7996/mtk_debugfs.c
 +++ b/mt7996/mtk_debugfs.c
-@@ -2325,6 +2325,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
- 	return 0;
- }
+@@ -2417,6 +2417,232 @@ mt7996_scs_enable_set(void *data, u64 val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL,
+ 			 mt7996_scs_enable_set, "%lld\n");
  
 +static int
 +mt7996_txpower_level_set(void *data, u64 val)
@@ -387,7 +377,7 @@
  int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
  {
  	struct mt7996_dev *dev = phy->dev;
-@@ -2367,6 +2593,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+@@ -2480,6 +2706,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,10 +388,10 @@
  	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 e887016..f772243 100644
+index c16b25ab..e56ddd8f 100644
 --- a/mt7996/mtk_mcu.c
 +++ b/mt7996/mtk_mcu.c
-@@ -12,7 +12,30 @@
+@@ -12,8 +12,31 @@
  
  #ifdef CONFIG_MTK_DEBUG
  
@@ -431,14 +421,15 @@
 +	return 0;
 +}
  
- #endif
+ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
+ {
 diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
-index e741aa2..beb1aba 100644
+index 7f4d4e02..1eb27831 100644
 --- a/mt7996/mtk_mcu.h
 +++ b/mt7996/mtk_mcu.h
-@@ -10,6 +10,84 @@
- 
- #ifdef CONFIG_MTK_DEBUG
+@@ -14,6 +14,85 @@ enum {
+ 	UNI_CMD_MURU_DBG_INFO = 0x18,
+ };
  
 +struct txpower_basic_info {
 +	u8 category;
@@ -518,14 +509,15 @@
 +	UNI_TXPOWER_BASIC_INFO = 0,
 +	UNI_TXPOWER_PHY_RATE_INFO = 5,
 +};
- 
++
  #endif
  
+ #endif
 diff --git a/mt7996/regs.h b/mt7996/regs.h
-index de5df91..565022a 100644
+index 4c20a67d..e94f9a90 100644
 --- a/mt7996/regs.h
 +++ b/mt7996/regs.h
-@@ -672,24 +672,31 @@ enum offs_rev {
+@@ -693,24 +693,31 @@ enum offs_rev {
  						 ((_wf) << 16) + (ofs))
  #define MT_WF_PHYRX_CSD_IRPI(_band, _wf)	MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-mtk-wifi-mt76-mt7996-add-single-sku.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-mtk-wifi-mt76-mt7996-add-single-sku.patch
new file mode 100644
index 0000000..f97c32c
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-mtk-wifi-mt76-mt7996-add-single-sku.patch
@@ -0,0 +1,277 @@
+From 646335d03eb96579459ba8f07c2e721d77188b10 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
+Date: Mon, 10 Jul 2023 19:56:16 +0800
+Subject: [PATCH 1008/1041] mtk: wifi: mt76: mt7996: add single sku
+
+Add single sku and default enable sku.
+
+Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+---
+ eeprom.c          | 50 ++++++++++++++++++++++++++++++++++++++++++-----
+ mt76.h            |  9 +++++++++
+ mt76_connac_mcu.c |  2 +-
+ mt7996/init.c     |  2 ++
+ mt7996/main.c     |  9 +++++++++
+ mt7996/mcu.c      | 41 ++++++++++++++++++++++++++++++++++----
+ mt7996/mt7996.h   |  1 +
+ 7 files changed, 104 insertions(+), 10 deletions(-)
+
+diff --git a/eeprom.c b/eeprom.c
+index 85bd2a29..c5be2843 100644
+--- a/eeprom.c
++++ b/eeprom.c
+@@ -341,6 +341,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,
++			      struct mt76_power_path_limits *dest_path,
+ 			      s8 target_power)
+ {
+ 	struct mt76_dev *dev = phy->dev;
+@@ -348,16 +349,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 = -127;
++	s8 max_power_backoff = -127;
+ 	s8 txs_delta;
++	int n_chains = hweight16(phy->chainmask);
++	s8 target_power_combine = target_power + mt76_tx_power_nss_delta(n_chains);
+ 
+ 	if (!mcs_rates)
+-		mcs_rates = 10;
++		mcs_rates = 12;
+ 
+ 	memset(dest, target_power, sizeof(*dest));
++	if (dest_path != NULL)
++		memset(dest_path, 0, sizeof(*dest_path));
+ 
+ 	if (!IS_ENABLED(CONFIG_OF))
+ 		return target_power;
+@@ -405,12 +410,47 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ 				     ARRAY_SIZE(dest->mcs), val, len,
+ 				     target_power, txs_delta, &max_power);
+ 
+-	val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
++	val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
+ 	mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+ 				     ARRAY_SIZE(dest->ru), val, len,
+ 				     target_power, txs_delta, &max_power);
+ 
+-	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_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_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_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_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_combine, txs_delta, &max_power_backoff);
++
++	if (max_power_backoff == target_power_combine)
++		return max_power;
++
++	return max_power_backoff;
+ }
+ EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
+ 
+diff --git a/mt76.h b/mt76.h
+index b0897ac2..19c445b5 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -1053,6 +1053,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 {
+ 	u64 *data;
+ 	int idx;
+@@ -1655,6 +1663,7 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan);
+ 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_tx_free(struct mt76_queue *q)
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index 52237583..6cb47699 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -2150,7 +2150,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,
+-						   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 c9c7c20a..af2f4143 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -295,6 +295,7 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
+ 	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;
++	struct mt76_power_path_limits limits_path;
+ 
+ 	for (i = 0; i < sband->n_channels; i++) {
+ 		struct ieee80211_channel *chan = &sband->channels[i];
+@@ -303,6 +304,7 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
+ 		target_power += pwr_delta;
+ 		target_power = mt76_get_rate_power_limits(phy->mt76, chan,
+ 							  &limits,
++							  &limits_path,
+ 							  target_power);
+ 		target_power += nss_delta;
+ 		target_power = DIV_ROUND_UP(target_power, 2);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 97f1ef8c..9481fc5c 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -77,6 +77,15 @@ int mt7996_run(struct ieee80211_hw *hw)
+ 	if (ret)
+ 		goto out;
+ 
++#ifdef CONFIG_MTK_DEBUG
++	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
++					   !dev->dbg.sku_disable);
++#else
++	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, true);
++#endif
++	if (ret)
++		goto out;
++
+ 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+ 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index cc417039..d8e5c220 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4491,6 +4491,7 @@ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id)
+ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ {
+ #define TX_POWER_LIMIT_TABLE_RATE	0
++#define TX_POWER_LIMIT_TABLE_PATH	1
+ 	struct mt7996_dev *dev = phy->dev;
+ 	struct mt76_phy *mphy = phy->mt76;
+ 	struct ieee80211_hw *hw = mphy->hw;
+@@ -4504,22 +4505,23 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ 		u8 band_idx;
+ 	} __packed req = {
+ 		.tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
+-		.len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4),
++		.len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4),
+ 		.power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
+ 		.power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
+ 		.band_idx = phy->mt76->band_idx,
+ 	};
+ 	struct mt76_power_limits la = {};
++	struct mt76_power_path_limits la_path = {};
+ 	struct sk_buff *skb;
+-	int i, tx_power;
++	int i, ret, tx_power;
+ 
+ 	tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
+ 	tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
+-					      &la, tx_power);
++					      &la, &la_path, tx_power);
+ 	mphy->txpower_cur = tx_power;
+ 
+ 	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
+-				 sizeof(req) + MT7996_SKU_RATE_NUM);
++				 sizeof(req) + MT7996_SKU_PATH_NUM);
+ 	if (!skb)
+ 		return -ENOMEM;
+ 
+@@ -4542,6 +4544,37 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ 	/* eht */
+ 	skb_put_data(skb, &la.eht[0], sizeof(la.eht));
+ 
++	/* padding */
++	skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
++
++	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
++				    MCU_WM_UNI_CMD(TXPOWER), true);
++	if (ret)
++		return ret;
++
++	/* only set per-path power table when it's configured */
++	if (!la_path.ofdm[0])
++		return 0;
++
++	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
++				 sizeof(req) + MT7996_SKU_PATH_NUM);
++	if (!skb)
++		return -ENOMEM;
++	req.power_limit_type = TX_POWER_LIMIT_TABLE_PATH;
++
++	skb_put_data(skb, &req, sizeof(req));
++	skb_put_data(skb, &la_path.cck, sizeof(la_path.cck));
++	skb_put_data(skb, &la_path.ofdm, sizeof(la_path.ofdm));
++	skb_put_data(skb, &la_path.ofdm_bf, sizeof(la_path.ofdm_bf));
++
++	for (i = 0; i < 32; i++) {
++		bool bf = i % 2;
++		u8 idx = i / 2;
++		s8 *buf = bf ? la_path.ru_bf[idx] : la_path.ru[idx];
++
++		skb_put_data(skb, buf, sizeof(la_path.ru[0]));
++	}
++
+ 	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ 				     MCU_WM_UNI_CMD(TXPOWER), true);
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 18a6a46d..7e3d381e 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -71,6 +71,7 @@
+ #define MT7996_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
+ 
+ #define MT7996_SKU_RATE_NUM		417
++#define MT7996_SKU_PATH_NUM		494
+ 
+ #define MT7996_MAX_TWT_AGRT		16
+ #define MT7996_MAX_STA_TWT_AGRT		8
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-mtk-wifi-mt76-mt7996-add-binfile-mode-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-mtk-wifi-mt76-mt7996-add-binfile-mode-support.patch
new file mode 100644
index 0000000..ad36e1a
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-mtk-wifi-mt76-mt7996-add-binfile-mode-support.patch
@@ -0,0 +1,366 @@
+From f7bb6a600c1dfd47dfc99ca7a80dac4178ea2581 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 1009/1041] mtk: wifi: mt76: mt7996: add binfile mode support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Fix binfile cannot sync precal data to atenl
+Binfile is viewed as efuse mode in atenl, so atenl does not allocate
+precal memory for its eeprom file
+Use mtd offset == 0xFFFFFFFF to determine whether it is binfile or flash mode
+Add support for loading precal in binfile mode
+
+Align upstream
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ eeprom.c             |  25 +++++++++++
+ mt76.h               |   3 ++
+ mt7996/eeprom.c      | 103 ++++++++++++++++++++++++++++++++++++++++---
+ mt7996/eeprom.h      |   7 +++
+ mt7996/mt7996.h      |   4 ++
+ mt7996/mtk_debugfs.c |  41 +++++++++++++++++
+ testmode.h           |   2 +-
+ 7 files changed, 179 insertions(+), 6 deletions(-)
+
+diff --git a/eeprom.c b/eeprom.c
+index c5be2843..adb87924 100644
+--- a/eeprom.c
++++ b/eeprom.c
+@@ -161,6 +161,31 @@ static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len)
+ 	return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len);
+ }
+ 
++bool mt76_check_bin_file_mode(struct mt76_dev *dev)
++{
++	struct device_node *np = dev->dev->of_node;
++	const char *bin_file_name = NULL;
++
++	if (!np)
++		return false;
++
++	of_property_read_string(np, "bin_file_name", &bin_file_name);
++
++	dev->bin_file_name = bin_file_name;
++	if (dev->bin_file_name) {
++		dev_info(dev->dev, "Using bin file %s\n", dev->bin_file_name);
++#ifdef CONFIG_NL80211_TESTMODE
++		dev->test_mtd.name = devm_kstrdup(dev->dev, bin_file_name, GFP_KERNEL);
++		dev->test_mtd.offset = -1;
++#endif
++	}
++
++	of_node_put(np);
++
++	return dev->bin_file_name ? true : false;
++}
++EXPORT_SYMBOL_GPL(mt76_check_bin_file_mode);
++
+ void
+ mt76_eeprom_override(struct mt76_phy *phy)
+ {
+diff --git a/mt76.h b/mt76.h
+index 19c445b5..1eb5a52b 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -948,6 +948,8 @@ struct mt76_dev {
+ 		struct mt76_usb usb;
+ 		struct mt76_sdio sdio;
+ 	};
++
++	const char *bin_file_name;
+ };
+ 
+ /* per-phy stats.  */
+@@ -1204,6 +1206,7 @@ void mt76_eeprom_override(struct mt76_phy *phy);
+ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len);
+ int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep,
+ 				const char *cell_name, int len);
++bool mt76_check_bin_file_mode(struct mt76_dev *dev);
+ 
+ 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 6c1966b7..c553a0f5 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -79,10 +79,17 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ 	}
+ }
+ 
+-static char *mt7996_eeprom_name(struct mt7996_dev *dev)
++const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ {
+-	if (dev->testmode_enable)
+-		return MT7996_EEPROM_DEFAULT_TM;
++	if (dev->bin_file_mode)
++		return dev->mt76.bin_file_name;
++
++	if (dev->testmode_enable) {
++		if (is_mt7992(&dev->mt76))
++			return MT7992_EEPROM_DEFAULT_TM;
++		else
++			return MT7996_EEPROM_DEFAULT_TM;
++	}
+ 
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
+@@ -149,7 +156,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+ 		return ret;
+ 
+ 	if (!fw || !fw->data) {
+-		dev_err(dev->mt76.dev, "Invalid default bin\n");
++		if (dev->bin_file_mode)
++			dev_err(dev->mt76.dev, "Invalid bin (bin file mode)\n");
++		else
++			dev_err(dev->mt76.dev, "Invalid default bin\n");
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+@@ -163,18 +173,45 @@ out:
+ 	return ret;
+ }
+ 
++static int mt7996_eeprom_load_flash(struct mt7996_dev *dev)
++{
++	int ret = 1;
++
++	/* 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.data = devm_kzalloc(dev->mt76.dev, dev->mt76.eeprom.size,
++						     GFP_KERNEL);
++		if (!dev->mt76.eeprom.data)
++			return -ENOMEM;
++
++		if (mt7996_eeprom_load_default(dev))
++			return 0;
++
++		if (mt7996_check_eeprom(dev))
++			return 0;
++	} else {
++		ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
++	}
++
++	return ret;
++}
++
+ int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev)
+ {
+ 	u8 *eeprom;
+ 	int ret;
+ 
+ 	/* load eeprom in flash or bin file mode to determine fw mode */
+-	ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
++	ret = mt7996_eeprom_load_flash(dev);
++
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	if (ret) {
+ 		dev->flash_mode = true;
++		dev->eeprom_mode = dev->bin_file_mode ? BIN_FILE_MODE : FLASH_MODE;
+ 		eeprom = dev->mt76.eeprom.data;
+ 		/* testmode enable priority: eeprom field > module parameter */
+ 		dev->testmode_enable = !mt7996_check_eeprom(dev) ? eeprom[MT_EE_TESTMODE_EN] :
+@@ -208,6 +245,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+ 			if (ret < 0)
+ 				return ret;
+ 		}
++		dev->eeprom_mode = EFUSE_MODE;
+ 	}
+ 
+ 	return mt7996_check_eeprom(dev);
+@@ -334,6 +372,59 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
+ 	return mt7996_eeprom_parse_band_config(phy);
+ }
+ 
++static int
++mt7996_eeprom_load_precal_binfile(struct mt7996_dev *dev, u32 offs, u32 size)
++{
++	const struct firmware *fw = NULL;
++	int ret;
++
++	ret = request_firmware(&fw, dev->mt76.bin_file_name, dev->mt76.dev);
++	if (ret)
++		return ret;
++
++	if (!fw || !fw->data) {
++		dev_err(dev->mt76.dev, "Invalid bin (bin file mode), load precal fail\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++	memcpy(dev->cal, fw->data + offs, size);
++
++out:
++	release_firmware(fw);
++
++	return ret;
++}
++
++static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
++{
++	struct mt76_dev *mdev = &dev->mt76;
++	u8 *eeprom = mdev->eeprom.data;
++	u32 offs = MT_EE_DO_PRE_CAL;
++	u32 size, val = eeprom[offs];
++	int ret;
++
++	mt7996_eeprom_init_precal(dev);
++
++	if (!dev->flash_mode || !val)
++		return 0;
++
++	size = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
++
++	dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++	if (!dev->cal)
++		return -ENOMEM;
++
++	if (dev->bin_file_mode)
++		return mt7996_eeprom_load_precal_binfile(dev, MT_EE_PRECAL, size);
++
++	ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);
++	if (!ret)
++		return ret;
++
++	return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
++}
++
+ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ {
+ 	int ret;
+@@ -348,6 +439,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ 			return ret;
+ 
+ 		dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
++		dev->bin_file_mode = false;
++		dev->eeprom_mode = DEFAULT_BIN_MODE;
+ 		ret = mt7996_eeprom_load_default(dev);
+ 		if (ret)
+ 			return ret;
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 23d4929d..8b555aeb 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -100,6 +100,13 @@ enum mt7996_eeprom_band {
+ 	MT_EE_BAND_SEL_6GHZ,
+ };
+ 
++enum mt7915_eeprom_mode {
++	DEFAULT_BIN_MODE,
++	EFUSE_MODE,
++	FLASH_MODE,
++	BIN_FILE_MODE,
++};
++
+ static inline int
+ mt7996_get_channel_group_5g(int channel)
+ {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 7e3d381e..2f067988 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -62,6 +62,7 @@
+ #define MT7992_EEPROM_DEFAULT_24	"mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
+ #define MT7992_EEPROM_DEFAULT_23	"mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"
+ #define MT7992_EEPROM_DEFAULT_23_EXT	"mediatek/mt7996/mt7992_eeprom_23_2e5e.bin"
++#define MT7992_EEPROM_DEFAULT_TM	"mediatek/mt7996/mt7992_eeprom_tm.bin"
+ #define MT7996_EEPROM_SIZE		7680
+ #define MT7996_EEPROM_BLOCK_SIZE	16
+ #define MT7996_TOKEN_SIZE		16384
+@@ -389,6 +390,8 @@ struct mt7996_dev {
+ 	} wed_rro;
+ 
+ 	bool testmode_enable;
++	bool bin_file_mode;
++	u8 eeprom_mode;
+ 
+ 	bool ibf;
+ 	u8 fw_debug_wm;
+@@ -516,6 +519,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);
++const char *mt7996_eeprom_name(struct mt7996_dev *dev);
+ int mt7996_eeprom_init(struct mt7996_dev *dev);
+ 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 93428851..fe6492ab 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2643,6 +2643,44 @@ static const struct file_operations mt7996_txpower_sku_fops = {
+ 	.llseek = default_llseek,
+ };
+ 
++static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt76_dev *mdev = &dev->mt76;
++#ifdef CONFIG_NL80211_TESTMODE
++	const char *mtd_name = mdev->test_mtd.name;
++	u32 mtd_offset = mdev->test_mtd.offset;
++#else
++	const char *mtd_name = NULL;
++	u32 mtd_offset;
++#endif
++
++	seq_printf(s, "Current eeprom mode:\n");
++
++	switch (dev->eeprom_mode) {
++	case DEFAULT_BIN_MODE:
++		seq_printf(s, "   default bin mode\n   filename = %s\n", mt7996_eeprom_name(dev));
++		break;
++	case EFUSE_MODE:
++		seq_printf(s, "   efuse mode\n");
++		break;
++	case FLASH_MODE:
++		if (mtd_name)
++			seq_printf(s, "   flash mode\n   mtd name = %s\n   flash offset = 0x%x\n",
++				   mtd_name, mtd_offset);
++		else
++			seq_printf(s, "   flash mode\n");
++		break;
++	case BIN_FILE_MODE:
++		seq_printf(s, "   bin file mode\n   filename = %s\n", mt7996_eeprom_name(dev));
++		break;
++	default:
++		break;
++	}
++
++	return 0;
++}
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2710,6 +2748,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 	debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
+ 	debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
+ 
++	debugfs_create_devm_seqfile(dev->mt76.dev, "eeprom_mode", dir,
++				    mt7996_show_eeprom_mode);
++
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
+ 				    mt7996_wtbl_read);
+ 
+diff --git a/testmode.h b/testmode.h
+index d6601cdc..5d677f8c 100644
+--- a/testmode.h
++++ b/testmode.h
+@@ -16,7 +16,7 @@
+  * @MT76_TM_ATTR_RESET: reset parameters to default (flag)
+  * @MT76_TM_ATTR_STATE: test state (u32), see &enum mt76_testmode_state
+  *
+- * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
++ * @MT76_TM_ATTR_MTD_PART: mtd partition or binfile used for eeprom data (string)
+  * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
+  * @MT76_TM_ATTR_BAND_IDX: band idx of the chip (u8)
+  *
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-mtk-wifi-mt76-mt7996-add-normal-mode-pre-calibration.patch
similarity index 80%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-mtk-wifi-mt76-mt7996-add-normal-mode-pre-calibration.patch
index 3aac8a9..487adb7 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1010-mtk-wifi-mt76-mt7996-add-normal-mode-pre-calibration.patch
@@ -1,25 +1,25 @@
-From 114d3abef99827bcc848e6aef393be79a7c34e71 Mon Sep 17 00:00:00 2001
+From 6f2a22fee13ed919b2867ed08f106a4a31e8db79 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 45/98] wifi: mt76: mt7996: add normal mode pre-calibration
- support
+Subject: [PATCH 1010/1041] mtk: wifi: mt76: mt7996: add normal mode
+ pre-calibration support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  mt76_connac_mcu.h |   1 +
- mt7996/eeprom.c   |  23 +++++++
+ mt7996/eeprom.c   |   4 ++
  mt7996/eeprom.h   |   2 +
  mt7996/init.c     |   6 ++
  mt7996/main.c     |   6 ++
  mt7996/mcu.c      | 166 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mt7996.h   |   2 +
- 7 files changed, 206 insertions(+)
+ mt7996/mt7996.h   |   3 +
+ 7 files changed, 188 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index d65ecf0..762ac29 100644
+index 5e1b15c4..1f0cd6e8 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1251,6 +1251,7 @@ enum {
+@@ -1266,6 +1266,7 @@ enum {
  	MCU_UNI_CMD_PP = 0x38,
  	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
  	MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
@@ -28,36 +28,10 @@
  	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
  	MCU_UNI_CMD_PER_STA_INFO = 0x6d,
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index ca91c69..56605de 100644
+index c553a0f5..372a822f 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
-@@ -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);
- }
- 
-+static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
-+{
-+	struct mt76_dev *mdev = &dev->mt76;
-+	u8 *eeprom = mdev->eeprom.data;
-+	u32 offs = MT_EE_DO_PRE_CAL;
-+	u32 size, val = eeprom[offs];
-+
-+	if (!dev->flash_mode || !val)
-+		return 0;
-+
-+	size = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
-+
-+	dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
-+	if (!dev->cal)
-+		return -ENOMEM;
-+
-+	return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, size);
-+}
-+
- int mt7996_eeprom_init(struct mt7996_dev *dev)
- {
- 	int ret;
-@@ -350,6 +369,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+@@ -446,6 +446,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
  			return ret;
  	}
  
@@ -69,7 +43,7 @@
  	if (ret < 0)
  		return ret;
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 20dd877..0f3f31d 100644
+index 8b555aeb..8f0f87b6 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
 @@ -25,6 +25,8 @@ enum mt7996_eeprom_field {
@@ -82,10 +56,10 @@
  
  #define MT_EE_WIFI_CONF0_TX_PATH		GENMASK(2, 0)
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 5940e41..bf3479e 100644
+index af2f4143..7cf7b0c2 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -826,6 +826,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -988,6 +988,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
  	if (ret < 0)
  		return ret;
  
@@ -99,10 +73,10 @@
  	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
  	if (idx)
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 804c0c1..7d1bd42 100644
+index 9481fc5c..ae9484c3 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -312,6 +312,12 @@ int mt7996_set_channel(struct mt7996_phy *phy)
+@@ -321,6 +321,12 @@ int mt7996_set_channel(struct mt7996_phy *phy)
  
  	mt76_set_channel(phy->mt76);
  
@@ -112,14 +86,14 @@
 +			goto out;
 +	}
 +
- 	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
- 	if (ret)
+ 	if (mt76_testmode_enabled(phy->mt76) || phy->mt76->test.bf_en) {
+ 		mt7996_tm_update_channel(phy);
  		goto out;
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index d6f4e22..695d5f0 100644
+index d8e5c220..fdddf457 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -3456,6 +3456,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
+@@ -3624,6 +3624,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
  	return 0;
  }
  
@@ -293,18 +267,19 @@
  {
  #define NIC_CAP	3
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index cda557e..80a10bf 100644
+index 2f067988..69db055d 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -611,6 +611,8 @@ void mt7996_mcu_exit(struct mt7996_dev *dev);
+@@ -611,6 +611,9 @@ void mt7996_mcu_exit(struct mt7996_dev *dev);
  int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
  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_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);
- int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
- void mt7996_mcu_scs_sta_poll(struct work_struct *work);
  #ifdef CONFIG_NL80211_TESTMODE
+ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ #endif
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-mtk-wifi-mt76-testmode-add-testmode-ZWDFS-verificati.patch
similarity index 94%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-mtk-wifi-mt76-testmode-add-testmode-ZWDFS-verificati.patch
index 16439d4..dfcf033 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-mtk-wifi-mt76-testmode-add-testmode-ZWDFS-verificati.patch
@@ -1,8 +1,8 @@
-From 9bbc79e25d5fe7c14ec520413f4fb0625af9c630 Mon Sep 17 00:00:00 2001
+From 0557d0114d56520ddf0f86312401a5a024494091 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 47/98] wifi: mt76: testmode: add testmode ZWDFS verification
- support
+Subject: [PATCH 1011/1041] mtk: 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 0bf0177..0096c7f 100644
+index 1eb5a52b..46fbc87e 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -774,6 +774,14 @@ struct mt76_testmode_data {
+@@ -777,6 +777,14 @@ struct mt76_testmode_data {
  	} cfg;
  
  	u8 aid;
@@ -34,10 +34,10 @@
  
  struct mt76_vif {
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 9f99d13..7269076 100644
+index 69db055d..2daca449 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -272,6 +272,7 @@ struct mt7996_phy {
+@@ -289,6 +289,7 @@ struct mt7996_phy {
  
  	struct mt76_mib_stats mib;
  	struct mt76_channel_state state_ts;
@@ -46,7 +46,7 @@
  	bool has_aux_rx;
  
 diff --git a/mt7996/testmode.c b/mt7996/testmode.c
-index 8ceea00..c52bf41 100644
+index 36be0ff8..26ae5827 100644
 --- a/mt7996/testmode.c
 +++ b/mt7996/testmode.c
 @@ -17,6 +17,12 @@ enum {
@@ -105,7 +105,7 @@
  	};
  
  	if (width >= ARRAY_SIZE(width_to_bw))
-@@ -216,6 +233,9 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en)
+@@ -217,6 +234,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
-@@ -828,6 +848,204 @@ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -829,6 +849,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)
  {
-@@ -858,6 +1076,14 @@ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+@@ -860,6 +1078,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 17c1456..57fde8c 100644
+index 9bfb86f2..78662b2e 100644
 --- a/mt7996/testmode.h
 +++ b/mt7996/testmode.h
 @@ -27,9 +27,15 @@ enum {
@@ -355,7 +355,7 @@
  
  	NUM_BW_MAP,
  };
-@@ -310,4 +316,42 @@ struct mt7996_tm_rx_event {
+@@ -312,4 +318,42 @@ struct mt7996_tm_rx_event {
  	};
  } __packed;
  
@@ -399,7 +399,7 @@
 +
  #endif
 diff --git a/testmode.c b/testmode.c
-index e66b54a..bce3a9c 100644
+index 7ed58a77..805ad83c 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -27,6 +27,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -416,7 +416,7 @@
  };
  EXPORT_SYMBOL_GPL(mt76_tm_policy);
  
-@@ -456,6 +463,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -499,6 +506,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,
-@@ -471,7 +481,14 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -514,7 +524,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,7 +442,7 @@
  		goto out;
  
  	if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -677,6 +694,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -720,6 +737,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) ||
@@ -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 b012276..77696ce 100644
+index b0122763..77696ce7 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -35,6 +35,15 @@ static const char * const testmode_tx_mode[] = {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch
deleted file mode 100644
index 6d1a987..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1011-wifi-mt76-mt7996-add-binfile-mode-support.patch
+++ /dev/null
@@ -1,260 +0,0 @@
-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 44/98] wifi: mt76: mt7996: add binfile mode support
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- eeprom.c             | 20 ++++++++++++++++++++
- mt76.h               |  3 +++
- mt7996/eeprom.c      | 42 +++++++++++++++++++++++++++++++++++++++---
- mt7996/eeprom.h      |  7 +++++++
- mt7996/mt7996.h      |  3 +++
- mt7996/mtk_debugfs.c | 40 ++++++++++++++++++++++++++++++++++++++++
- 6 files changed, 112 insertions(+), 3 deletions(-)
-
-diff --git a/eeprom.c b/eeprom.c
-index 437d8ca..89bb913 100644
---- a/eeprom.c
-+++ b/eeprom.c
-@@ -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);
- 
-+bool mt76_check_bin_file_mode(struct mt76_dev *dev)
-+{
-+	struct device_node *np = dev->dev->of_node;
-+	const char *bin_file_name = NULL;
-+
-+	if (!np)
-+		return false;
-+
-+	of_property_read_string(np, "bin_file_name", &bin_file_name);
-+
-+	dev->bin_file_name = bin_file_name;
-+	if (dev->bin_file_name)
-+		dev_info(dev->dev, "Using bin file %s\n", dev->bin_file_name);
-+
-+	of_node_put(np);
-+
-+	return dev->bin_file_name ? true : false;
-+}
-+EXPORT_SYMBOL_GPL(mt76_check_bin_file_mode);
-+
- void
- mt76_eeprom_override(struct mt76_phy *phy)
- {
-diff --git a/mt76.h b/mt76.h
-index fc69d3e..0bf0177 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -945,6 +945,8 @@ struct mt76_dev {
- 		struct mt76_usb usb;
- 		struct mt76_sdio sdio;
- 	};
-+
-+	const char *bin_file_name;
- };
- 
- /* 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);
-+bool mt76_check_bin_file_mode(struct mt76_dev *dev);
- 
- 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 b88fd64..ca91c69 100644
---- a/mt7996/eeprom.c
-+++ b/mt7996/eeprom.c
-@@ -61,8 +61,11 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
- 	}
- }
- 
--static char *mt7996_eeprom_name(struct mt7996_dev *dev)
-+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;
-@@ -114,7 +117,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
- 		return ret;
- 
- 	if (!fw || !fw->data) {
--		dev_err(dev->mt76.dev, "Invalid default bin\n");
-+		if (dev->bin_file_mode)
-+			dev_err(dev->mt76.dev, "Invalid bin (bin file mode)\n");
-+		else
-+			dev_err(dev->mt76.dev, "Invalid default bin\n");
- 		ret = -EINVAL;
- 		goto out;
- 	}
-@@ -128,18 +134,45 @@ out:
- 	return ret;
- }
- 
-+static int mt7996_eeprom_load_flash(struct mt7996_dev *dev)
-+{
-+	int ret = 1;
-+
-+	/* 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.data = devm_kzalloc(dev->mt76.dev, dev->mt76.eeprom.size,
-+						     GFP_KERNEL);
-+		if (!dev->mt76.eeprom.data)
-+			return -ENOMEM;
-+
-+		if (mt7996_eeprom_load_default(dev))
-+			return 0;
-+
-+		if (mt7996_check_eeprom(dev))
-+			return 0;
-+	} else {
-+		ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
-+	}
-+
-+	return ret;
-+}
-+
- int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev)
- {
- 	u8 *eeprom;
- 	int ret;
- 
- 	/* load eeprom in flash or bin file mode to determine fw mode */
--	ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
-+	ret = mt7996_eeprom_load_flash(dev);
-+
- 	if (ret < 0)
- 		return ret;
- 
- 	if (ret) {
- 		dev->flash_mode = true;
-+		dev->eeprom_mode = dev->bin_file_mode ? BIN_FILE_MODE : FLASH_MODE;
- 		eeprom = dev->mt76.eeprom.data;
- 		/* testmode enable priority: eeprom field > module parameter */
- 		dev->testmode_enable = !mt7996_check_eeprom(dev) ? eeprom[MT_EE_TESTMODE_EN] :
-@@ -173,6 +206,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
- 			if (ret < 0)
- 				return ret;
- 		}
-+		dev->eeprom_mode = EFUSE_MODE;
- 	}
- 
- 	return mt7996_check_eeprom(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");
-+		dev->bin_file_mode = false;
-+		dev->eeprom_mode = DEFAULT_BIN_MODE;
- 		ret = mt7996_eeprom_load_default(dev);
- 		if (ret)
- 			return ret;
-diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 7ff290f..20dd877 100644
---- a/mt7996/eeprom.h
-+++ b/mt7996/eeprom.h
-@@ -99,6 +99,13 @@ enum mt7996_eeprom_band {
- 	MT_EE_BAND_SEL_6GHZ,
- };
- 
-+enum mt7915_eeprom_mode {
-+	DEFAULT_BIN_MODE,
-+	EFUSE_MODE,
-+	FLASH_MODE,
-+	BIN_FILE_MODE,
-+};
-+
- static inline int
- mt7996_get_channel_group_5g(int channel)
- {
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 684c254..cda557e 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -375,6 +375,8 @@ struct mt7996_dev {
- 	} wed_rro;
- 
- 	bool testmode_enable;
-+	bool bin_file_mode;
-+	u8 eeprom_mode;
- 
- 	bool ibf;
- 	u8 fw_debug_wm;
-@@ -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);
-+const char *mt7996_eeprom_name(struct mt7996_dev *dev);
- int mt7996_eeprom_init(struct mt7996_dev *dev);
- 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 57fcbab..82b2785 100644
---- a/mt7996/mtk_debugfs.c
-+++ b/mt7996/mtk_debugfs.c
-@@ -2551,6 +2551,44 @@ static const struct file_operations mt7996_txpower_sku_fops = {
- 	.llseek = default_llseek,
- };
- 
-+static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
-+{
-+	struct mt7996_dev *dev = dev_get_drvdata(s->private);
-+	struct mt76_dev *mdev = &dev->mt76;
-+#ifdef CONFIG_NL80211_TESTMODE
-+	const char *mtd_name = mdev->test_mtd.name;
-+	u32 mtd_offset = mdev->test_mtd.offset;
-+#else
-+	const char *mtd_name = NULL;
-+	u32 mtd_offset;
-+#endif
-+
-+	seq_printf(s, "Current eeprom mode:\n");
-+
-+	switch (dev->eeprom_mode) {
-+	case DEFAULT_BIN_MODE:
-+		seq_printf(s, "   default bin mode\n   filename = %s\n", mt7996_eeprom_name(dev));
-+		break;
-+	case EFUSE_MODE:
-+		seq_printf(s, "   efuse mode\n");
-+		break;
-+	case FLASH_MODE:
-+		if (mtd_name)
-+			seq_printf(s, "   flash mode\n   mtd name = %s\n   flash offset = 0x%x\n",
-+				   mtd_name, mtd_offset);
-+		else
-+			seq_printf(s, "   flash mode\n");
-+		break;
-+	case BIN_FILE_MODE:
-+		seq_printf(s, "   bin file mode\n   filename = %s\n", mt7996_eeprom_name(dev));
-+		break;
-+	default:
-+		break;
-+	}
-+
-+	return 0;
-+}
-+
- int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
- {
- 	struct mt7996_dev *dev = phy->dev;
-@@ -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);
-+	debugfs_create_devm_seqfile(dev->mt76.dev, "eeprom_mode", dir,
-+				    mt7996_show_eeprom_mode);
- 
- 	debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
- 				    mt7996_wtbl_read);
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-mtk-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
similarity index 83%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-mtk-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
index 38754fa..322fd05 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1007-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1012-mtk-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
@@ -1,23 +1,30 @@
-From 6c7addb48070af33da842ede744264149f2a9110 Mon Sep 17 00:00:00 2001
+From 842decc15bd36d4a61f17cb8927fba77b6c58999 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 40/98] wifi: mt76: mt7996: add mu vendor command support
+Subject: [PATCH 1012/1041] mtk: wifi: mt76: mt7996: add mu vendor command
+ support
 
-Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
+mtk: wifi: mt76: fix muru_onoff as all enabled by default
+
+Fix muru_onoff default value as 0xF, which means all MU & RU are
+enabled. The purpose of this commit is to align muru_onoff value with
+hostapd and mt76 driver
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
 ---
  mt7996/Makefile |  3 +-
- mt7996/init.c   |  8 +++++
+ mt7996/init.c   |  9 ++++++
  mt7996/mcu.c    | 37 ++++++++++++++++++---
  mt7996/mcu.h    | 12 +++++++
- mt7996/mt7996.h |  6 ++++
+ mt7996/mt7996.h |  7 ++++
  mt7996/vendor.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
  mt7996/vendor.h | 22 +++++++++++++
- 7 files changed, 167 insertions(+), 6 deletions(-)
+ 7 files changed, 169 insertions(+), 6 deletions(-)
  create mode 100644 mt7996/vendor.c
  create mode 100644 mt7996/vendor.h
 
 diff --git a/mt7996/Makefile b/mt7996/Makefile
-index 7bb17f4..6643c7a 100644
+index 7bb17f44..6643c7a3 100644
 --- a/mt7996/Makefile
 +++ b/mt7996/Makefile
 @@ -1,11 +1,12 @@
@@ -35,10 +42,18 @@
  mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
  mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
 diff --git a/mt7996/init.c b/mt7996/init.c
-index f393e04..1f4e84d 100644
+index 7cf7b0c2..c4f0ec70 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -597,6 +597,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+@@ -368,6 +368,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
+ 
+ 	phy->slottime = 9;
+ 	phy->beacon_rate = -1;
++	phy->muru_onoff = OFDMA_UL | OFDMA_DL | MUMIMO_DL | MUMIMO_UL;
+ 
+ 	hw->sta_data_size = sizeof(struct mt7996_sta);
+ 	hw->vif_data_size = sizeof(struct mt7996_vif);
+@@ -621,6 +622,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
  	if (ret)
  		goto error;
  
@@ -49,7 +64,7 @@
  	ret = mt76_register_phy(mphy, true, mt76_rates,
  				ARRAY_SIZE(mt76_rates));
  	if (ret)
-@@ -1230,6 +1234,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1405,6 +1410,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
  	dev->mt76.test_ops = &mt7996_testmode_ops;
  #endif
  
@@ -61,10 +76,10 @@
  				   ARRAY_SIZE(mt76_rates));
  	if (ret)
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6cedc39..a008c08 100644
+index fdddf457..05fa855b 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1266,6 +1266,8 @@ static void
+@@ -1383,6 +1383,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 +88,7 @@
  	struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
  	struct sta_rec_muru *muru;
  	struct tlv *tlv;
-@@ -1277,11 +1279,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1394,11 +1396,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 +108,7 @@
  
  	if (sta->deflink.vht_cap.vht_supported)
  		muru->mimo_dl.vht_mu_bfee =
-@@ -4469,3 +4474,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+@@ -4913,3 +4918,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 +135,10 @@
 +}
 +#endif
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 71dc165..c5c0a44 100644
+index 887d9b49..68bf82fc 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -683,8 +683,20 @@ enum {
+@@ -754,8 +754,20 @@ enum {
  	RATE_PARAM_FIXED_MCS,
  	RATE_PARAM_FIXED_GI = 11,
  	RATE_PARAM_AUTO = 20,
@@ -145,18 +160,19 @@
  	BF_SOUNDING_ON = 1,
  	BF_HW_EN_UPDATE = 17,
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 23d1614..013122f 100644
+index 2daca449..d0b425da 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -249,6 +249,7 @@ struct mt7996_phy {
+@@ -295,6 +295,8 @@ struct mt7996_phy {
  
  	struct mt7996_scs_ctrl scs_ctrl;
  
 +	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,
+@@ -733,6 +735,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);
  
@@ -167,10 +183,10 @@
 +
  #ifdef CONFIG_MTK_DEBUG
  int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
- #endif
+ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
 diff --git a/mt7996/vendor.c b/mt7996/vendor.c
 new file mode 100644
-index 0000000..b5ecbdf
+index 00000000..b5ecbdf1
 --- /dev/null
 +++ b/mt7996/vendor.c
 @@ -0,0 +1,85 @@
@@ -261,7 +277,7 @@
 +}
 diff --git a/mt7996/vendor.h b/mt7996/vendor.h
 new file mode 100644
-index 0000000..8ac3ba8
+index 00000000..8ac3ba8e
 --- /dev/null
 +++ b/mt7996/vendor.h
 @@ -0,0 +1,22 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-mtk-wifi-mt76-mt7996-Add-air-monitor-support.patch
similarity index 95%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-mtk-wifi-mt76-mt7996-Add-air-monitor-support.patch
index 45f1585..5afff31 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1008-wifi-mt76-mt7996-Add-air-monitor-support.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-mtk-wifi-mt76-mt7996-Add-air-monitor-support.patch
@@ -1,7 +1,7 @@
-From 98127145e2f401f65029185adab6dfcb0e90dbd9 Mon Sep 17 00:00:00 2001
+From c541c6af3d962fb8eb8b844aab518702693ced12 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 41/98] wifi: mt76: mt7996: Add air monitor support
+Subject: [PATCH 1013/1041] mtk: 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 fae76c9..bbf600b 100644
+index 1f0cd6e8..fefa2a0c 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1222,6 +1222,7 @@ enum {
+@@ -1240,6 +1240,7 @@ enum {
  	MCU_UNI_CMD_REG_ACCESS = 0x0d,
  	MCU_UNI_CMD_CHIP_CONFIG = 0x0e,
  	MCU_UNI_CMD_POWER_CTRL = 0x0f,
@@ -25,7 +25,7 @@
  	MCU_UNI_CMD_SER = 0x13,
  	MCU_UNI_CMD_TWT = 0x14,
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 637f0f6..ee17d59 100644
+index e307ddc3..f7dc8db4 100644
 --- a/mt7996/mac.c
 +++ b/mt7996/mac.c
 @@ -679,6 +679,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
@@ -40,10 +40,10 @@
  		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 6fa4a65..804c0c1 100644
+index ae9484c3..2042edd6 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -696,6 +696,10 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+@@ -737,6 +737,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,11 +55,11 @@
  	if (ret)
  		return ret;
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 013122f..3c535be 100644
+index d0b425da..09ce3c35 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -205,6 +205,34 @@ enum {
- 	SCS_ENABLE,
+@@ -259,6 +259,34 @@ struct mt7996_wed_rro_session_id {
+ 	u16 id;
  };
  
 +#ifdef CONFIG_MTK_VENDOR
@@ -90,10 +90,10 @@
 +};
 +#endif
 +
- struct mt7996_wed_rro_addr {
- 	u32 head_low;
- 	u32 head_high : 4;
-@@ -264,6 +292,10 @@ struct mt7996_phy {
+ struct mt7996_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -311,6 +339,10 @@ struct mt7996_phy {
  		u8 spe_idx;
  	} test;
  #endif
@@ -104,7 +104,7 @@
  };
  
  struct mt7996_dev {
-@@ -687,6 +719,9 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+@@ -738,6 +770,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,7 +115,7 @@
  
  #ifdef CONFIG_MTK_DEBUG
 diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index b5ecbdf..f3b089d 100644
+index b5ecbdf1..f3b089d7 100644
 --- a/mt7996/vendor.c
 +++ b/mt7996/vendor.c
 @@ -16,6 +16,32 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
@@ -506,7 +506,7 @@
 +	spin_lock_init(&phy->amnt_lock);
  }
 diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index 8ac3ba8..2078caf 100644
+index 8ac3ba8e..2078cafa 100644
 --- a/mt7996/vendor.h
 +++ b/mt7996/vendor.h
 @@ -4,6 +4,7 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
deleted file mode 100644
index 9a38681..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1013-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
+++ /dev/null
@@ -1,343 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-mtk-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv.patch
similarity index 74%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-mtk-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv.patch
index 672885d..bfecc98 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1009-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1014-mtk-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv.patch
@@ -1,8 +1,8 @@
-From 786bd792b2a62dee5e4aca8aa09ed01be1731ec4 Mon Sep 17 00:00:00 2001
+From 3532bffff8a8d5665304f6abb337305c50174de4 Mon Sep 17 00:00:00 2001
 From: mtk23510 <rudra.shahi@mediatek.com>
 Date: Fri, 24 Mar 2023 19:18:53 +0800
-Subject: [PATCH 42/98] wifi: mt76: mt7996: add driver support for wpa3 ocv and
- bp mt76
+Subject: [PATCH 1014/1041] mtk: wifi: mt76: mt7996: add driver support for
+ wpa3 ocv and bp mt76
 
 Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
 ---
@@ -10,10 +10,10 @@
  1 file changed, 2 insertions(+)
 
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 1f4e84d..5940e41 100644
+index c4f0ec70..ab13021c 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -377,6 +377,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
+@@ -391,6 +391,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);
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-mtk-wifi-mt76-mt7996-add-vendor-cmd-to-get-available.patch
similarity index 92%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-mtk-wifi-mt76-mt7996-add-vendor-cmd-to-get-available.patch
index 37717c3..2e4efce 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-mtk-wifi-mt76-mt7996-add-vendor-cmd-to-get-available.patch
@@ -1,8 +1,8 @@
-From 8d1ba9d8e0f80eedcdf14d29dbca9c3cbd8589dc Mon Sep 17 00:00:00 2001
+From 5404f25b9db5bbeff8a4288f3709606290cd16f8 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 49/98] wifi: mt76: mt7996: add vendor cmd to get available
- color bitmap
+Subject: [PATCH 1015/1041] mtk: wifi: mt76: mt7996: add vendor cmd to get
+ available color bitmap
 
 Add a vendor cmd to notify user space available color bitmap.
 The OBSS BSS color bitmap is maintained in mac80211, so mt76 will make use of that.
@@ -14,7 +14,7 @@
  2 files changed, 47 insertions(+)
 
 diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index f3b089d..3910157 100644
+index f3b089d7..39101577 100644
 --- a/mt7996/vendor.c
 +++ b/mt7996/vendor.c
 @@ -35,6 +35,11 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
@@ -75,7 +75,7 @@
  
  void mt7996_vendor_register(struct mt7996_phy *phy)
 diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index 2078caf..eec9e74 100644
+index 2078cafa..eec9e74a 100644
 --- a/mt7996/vendor.h
 +++ b/mt7996/vendor.h
 @@ -6,6 +6,7 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-wifi-mt76-mt7996-add-single-sku.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-wifi-mt76-mt7996-add-single-sku.patch
deleted file mode 100644
index 14514e2..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1015-wifi-mt76-mt7996-add-single-sku.patch
+++ /dev/null
@@ -1,355 +0,0 @@
-From d07d8b3b246b974d7ae4ad9bdfc676438cb45fec Mon Sep 17 00:00:00 2001
-From: "Allen.Ye" <allen.ye@mediatek.com>
-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          | 50 +++++++++++++++++++++++---
- mt76.h            |  9 +++++
- mt76_connac_mcu.c |  2 +-
- mt7996/init.c     |  2 ++
- mt7996/main.c     | 16 +++++++++
- mt7996/mcu.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/mcu.h      | 12 +++++++
- mt7996/mt7996.h   |  2 ++
- 8 files changed, 179 insertions(+), 6 deletions(-)
-
-diff --git a/eeprom.c b/eeprom.c
-index 89bb913..bd662dd 100644
---- a/eeprom.c
-+++ b/eeprom.c
-@@ -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,
-+			      struct mt76_power_path_limits *dest_path,
- 			      s8 target_power)
- {
- 	struct mt76_dev *dev = phy->dev;
-@@ -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 = -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;
-+		mcs_rates = 12;
- 
- 	memset(dest, target_power, sizeof(*dest));
-+	if (dest_path != NULL)
-+		memset(dest_path, 0, sizeof(*dest_path));
- 
- 	if (!IS_ENABLED(CONFIG_OF))
- 		return target_power;
-@@ -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);
- 
--	val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
-+	val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
- 	mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
- 				     ARRAY_SIZE(dest->ru), val, len,
- 				     target_power, txs_delta, &max_power);
- 
--	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_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_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_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_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_combine, txs_delta, &max_power_backoff);
-+
-+	if (max_power_backoff == target_power_combine)
-+		return max_power;
-+
-+	return max_power_backoff;
- }
- EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
- 
-diff --git a/mt76.h b/mt76.h
-index 0096c7f..d59a1f5 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -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 {
- 	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_tx_free(struct mt76_queue *q)
-diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 236cfea..214a526 100644
---- a/mt76_connac_mcu.c
-+++ b/mt76_connac_mcu.c
-@@ -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,
--						   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 bf3479e..ad93927 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -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;
-+	struct mt76_power_path_limits limits_path;
- 
- 	for (i = 0; i < sband->n_channels; i++) {
- 		struct ieee80211_channel *chan = &sband->channels[i];
-@@ -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,
-+							  &limits_path,
- 							  target_power);
- 		target_power += nss_delta;
- 		target_power = DIV_ROUND_UP(target_power, 2);
-diff --git a/mt7996/main.c b/mt7996/main.c
-index 0ea006c..9e3e4ed 100644
---- a/mt7996/main.c
-+++ b/mt7996/main.c
-@@ -77,6 +77,15 @@ int mt7996_run(struct ieee80211_hw *hw)
- 	if (ret)
- 		goto out;
- 
-+#ifdef CONFIG_MTK_DEBUG
-+	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
-+					   !dev->dbg.sku_disable);
-+#else
-+	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, true);
-+#endif
-+	if (ret)
-+		goto out;
-+
- 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
- 
- 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-@@ -429,6 +438,12 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
- 		ieee80211_wake_queues(hw);
- 	}
- 
-+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+		ret = mt7996_mcu_set_txpower_sku(phy);
-+		if (ret)
-+			return ret;
-+	}
-+
- 	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 1a1c732..c87cb1a 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -4708,6 +4708,98 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
- 				 &req, sizeof(req), false);
- }
- 
-+int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
-+{
-+#define TX_POWER_LIMIT_TABLE_RATE	0
-+#define TX_POWER_LIMIT_TABLE_PATH	1
-+	struct mt7996_dev *dev = phy->dev;
-+	struct mt76_phy *mphy = phy->mt76;
-+	struct ieee80211_hw *hw = mphy->hw;
-+	struct tx_power_limit_table_ctrl {
-+		u8 __rsv1[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+		u8 power_ctrl_id;
-+		u8 power_limit_type;
-+		u8 band_idx;
-+	} __packed req = {
-+		.tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
-+		.len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4),
-+		.power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
-+		.power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
-+		.band_idx = phy->mt76->band_idx,
-+	};
-+
-+	int i, ret, tx_power;
-+	const u8 *len = mt7996_sku_group_len;
-+	struct mt76_power_limits la = {};
-+	struct mt76_power_path_limits la_path = {};
-+	struct sk_buff *skb;
-+
-+	tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
-+	tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
-+					      &la, &la_path, tx_power);
-+	mphy->txpower_cur = tx_power;
-+
-+	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
-+				 sizeof(req) + MT7996_SKU_PATH_NUM);
-+	if (!skb)
-+		return -ENOMEM;
-+
-+	skb_put_data(skb, &req, sizeof(req));
-+	skb_put_data(skb, &la.cck, len[SKU_CCK] + len[SKU_OFDM]);
-+
-+	skb_put_data(skb, &la.mcs[0], len[SKU_HT20]);
-+	skb_put_data(skb, &la.mcs[1], len[SKU_HT40]);
-+
-+	/* vht */
-+	for (i = 0; i < 4; i++) {
-+		skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i]));
-+		skb_put_zero(skb, 2);  /* padding */
-+	}
-+
-+	/* he */
-+	skb_put_data(skb, &la.ru[0], sizeof(la.ru));
-+
-+	/* eht */
-+	skb_put_data(skb, &la.eht[0], sizeof(la.eht));
-+
-+	/* padding */
-+	skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
-+
-+	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+				    MCU_WM_UNI_CMD(TXPOWER), true);
-+	if (ret)
-+		return ret;
-+
-+	/* only set per-path power table when it's configured */
-+	if (!la_path.ofdm[0])
-+		return 0;
-+
-+	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
-+				 sizeof(req) + MT7996_SKU_PATH_NUM);
-+	if (!skb)
-+		return -ENOMEM;
-+	req.power_limit_type = TX_POWER_LIMIT_TABLE_PATH;
-+
-+	skb_put_data(skb, &req, sizeof(req));
-+	skb_put_data(skb, &la_path.cck, sizeof(la_path.cck));
-+	skb_put_data(skb, &la_path.ofdm, sizeof(la_path.ofdm));
-+	skb_put_data(skb, &la_path.ofdm_bf, sizeof(la_path.ofdm_bf));
-+
-+	for (i = 0; i < 32; i++) {
-+		bool bf = i % 2;
-+		u8 idx = i / 2;
-+		s8 *buf = bf ? la_path.ru_bf[idx] : la_path.ru[idx];
-+
-+		skb_put_data(skb, buf, sizeof(la_path.ru[0]));
-+	}
-+
-+	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+				     MCU_WM_UNI_CMD(TXPOWER), 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 7808c35..6fc5ab3 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -777,6 +777,18 @@ enum {
- #define MT7996_MAX_BSS_OFFLOAD_SIZE	(MT7996_MAX_BEACON_SIZE +		\
- 					 MT7996_BEACON_UPDATE_SIZE)
- 
-+static inline s8
-+mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
-+{
-+	struct mt76_phy *mphy = phy->mt76;
-+	int n_chains = hweight8(mphy->antenna_mask);
-+
-+	txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
-+	txpower -= mt76_tx_power_nss_delta(n_chains);
-+
-+	return txpower;
-+}
-+
- enum {
- 	UNI_BAND_CONFIG_RADIO_ENABLE,
- 	UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 7269076..34c8fe6 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -64,6 +64,7 @@
- #define MT7996_BUILD_TIME_LEN		24
- 
- #define MT7996_SKU_RATE_NUM		417
-+#define MT7996_SKU_PATH_NUM		494
- 
- #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);
-+int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
- int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
- void mt7996_mcu_scs_sta_poll(struct work_struct *work);
- #ifdef CONFIG_NL80211_TESTMODE
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-mtk-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
similarity index 88%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-mtk-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
index da8c4bd..6039a11 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1016-mtk-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
@@ -1,7 +1,8 @@
-From 7556e60ec860e301a053dad4b16b7e88ccd9baa7 Mon Sep 17 00:00:00 2001
+From fc87a548d72adf02f817bfe4327973978cc69061 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 50/98] wifi: mt76: mt7996: add debugfs for fw coredump.
+Subject: [PATCH 1016/1041] mtk: wifi: mt76: mt7996: add debugfs for fw
+ coredump.
 
 Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
 ---
@@ -12,7 +13,7 @@
  4 files changed, 56 insertions(+), 5 deletions(-)
 
 diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 92aa164..2c11837 100644
+index f4ce3b55..67c6bd09 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 +65,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 ee17d59..37cc94e 100644
+index f7dc8db4..b92d7fe9 100644
 --- a/mt7996/mac.c
 +++ b/mt7996/mac.c
-@@ -2021,15 +2021,36 @@ void mt7996_mac_dump_work(struct work_struct *work)
+@@ -2083,15 +2083,36 @@ void mt7996_mac_dump_work(struct work_struct *work)
  	struct mt7996_dev *dev;
  
  	dev = container_of(work, struct mt7996_dev, dump_work);
@@ -107,7 +108,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)
+@@ -2109,6 +2130,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 +117,10 @@
  	}
  
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 6fc5ab3..989a2ff 100644
+index 68bf82fc..35f757dc 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -900,7 +900,11 @@ enum {
+@@ -956,7 +956,11 @@ enum {
  	UNI_CMD_SER_SET_RECOVER_L3_BF,
  	UNI_CMD_SER_SET_RECOVER_L4_MDP,
  	UNI_CMD_SER_SET_RECOVER_FULL,
@@ -132,10 +133,10 @@
  	UNI_CMD_SER_ENABLE = 1,
  	UNI_CMD_SER_SET,
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 34c8fe6..9b110cf 100644
+index 09ce3c35..dd9aa9e2 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -100,6 +100,14 @@ enum mt7996_ram_type {
+@@ -139,6 +139,14 @@ enum mt7996_ram_type {
  	__MT7996_RAM_TYPE_MAX,
  };
  
@@ -150,7 +151,7 @@
  enum mt7996_txq_id {
  	MT7996_TXQ_FWDL = 16,
  	MT7996_TXQ_MCU_WM,
-@@ -342,6 +350,7 @@ struct mt7996_dev {
+@@ -388,6 +396,7 @@ struct mt7996_dev {
  
  	/* protects coredump data */
  	struct mutex dump_mutex;
@@ -158,9 +159,9 @@
  #ifdef CONFIG_DEV_COREDUMP
  	struct {
  		struct mt7996_crash_data *crash_data[__MT7996_RAM_TYPE_MAX];
-@@ -541,6 +550,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
- 			 struct ieee80211_supported_band *sband);
+@@ -573,6 +582,7 @@ void mt7996_init_txpower(struct mt7996_phy *phy);
  int mt7996_txbf_init(struct mt7996_dev *dev);
+ int mt7996_get_chip_sku(struct mt7996_dev *dev);
  void mt7996_reset(struct mt7996_dev *dev);
 +void mt7996_coredump(struct mt7996_dev *dev, u8 state);
  int mt7996_run(struct ieee80211_hw *hw);
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch
similarity index 79%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch
index dc0b0c3..2a94253 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1017-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch
@@ -1,8 +1,8 @@
-From a928c6df5edd9920b4293de6d1216461952aec27 Mon Sep 17 00:00:00 2001
+From 0e6130e10742d6937b5f6ab69a7b0c2aea1d8b79 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 51/98] wifi: mt76: mt7996: add support for runtime set in-band
- discovery
+Subject: [PATCH 1017/1041] mtk: 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 c87cb1a..722c435 100644
+index 05fa855b..9331abb5 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -2484,8 +2484,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+@@ -2600,8 +2600,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 &&
-@@ -2521,7 +2520,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+@@ -2636,7 +2635,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);
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-mtk-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-en.patch
similarity index 89%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-mtk-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-en.patch
index 06fc5e8..4714bd7 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-enable.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1018-mtk-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-en.patch
@@ -1,37 +1,23 @@
-From 140f810c788ffccc605fa979635c9be2db4b9748 Mon Sep 17 00:00:00 2001
+From a0ddc3b5248671258de46c7f1b4fc4e26f6cf553 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
+Subject: [PATCH 1018/1041] mtk: 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.c |  87 +++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.h |  15 ++++++
  mt7996/vendor.c  | 132 +++++++++++++++++++++++++++++++++++++++++++++++
  mt7996/vendor.h  |  33 ++++++++++++
- 7 files changed, 282 insertions(+)
+ 6 files changed, 280 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
+index 35f757dc..34fdfb26 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -791,6 +791,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
+@@ -845,6 +845,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
  
  enum {
  	UNI_BAND_CONFIG_RADIO_ENABLE,
@@ -41,10 +27,10 @@
  };
  
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 9b110cf..8fd29d7 100644
+index dd9aa9e2..130e9b37 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -750,6 +750,17 @@ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
+@@ -785,6 +785,17 @@ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
  				  struct ieee80211_sta *sta);
  #endif
  
@@ -61,15 +47,16 @@
 +
  #ifdef CONFIG_MTK_DEBUG
  int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
- #endif
+ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
 diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
-index f772243..048c534 100644
+index e56ddd8f..5c54d02c 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;
+@@ -59,4 +59,91 @@ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
+ 	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
+ 				 sizeof(req), true);
  }
- 
++
 +int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable)
 +{
 +	struct mt7996_dev *dev = phy->dev;
@@ -158,10 +145,10 @@
 +
  #endif
 diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
-index beb1aba..9c0db87 100644
+index 1eb27831..1137fe5d 100644
 --- a/mt7996/mtk_mcu.h
 +++ b/mt7996/mtk_mcu.h
-@@ -89,6 +89,21 @@ enum txpower_event {
+@@ -93,6 +93,21 @@ enum txpower_event {
  	UNI_TXPOWER_PHY_RATE_INFO = 5,
  };
  
@@ -184,7 +171,7 @@
  
  #endif
 diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index 3910157..9f333d0 100644
+index 39101577..9f333d0e 100644
 --- a/mt7996/vendor.c
 +++ b/mt7996/vendor.c
 @@ -40,6 +40,26 @@ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
@@ -341,7 +328,7 @@
  
  void mt7996_vendor_register(struct mt7996_phy *phy)
 diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index eec9e74..4465bc9 100644
+index eec9e74a..4465bc9d 100644
 --- a/mt7996/vendor.h
 +++ b/mt7996/vendor.h
 @@ -6,9 +6,42 @@
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-mtk-wifi-mt76-mt7996-add-support-spatial-reuse-debug.patch
similarity index 88%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-mtk-wifi-mt76-mt7996-add-support-spatial-reuse-debug.patch
index 142193f..a0620a7 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-wifi-mt76-mt7996-add-support-spatial-reuse-debug-com.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1019-mtk-wifi-mt76-mt7996-add-support-spatial-reuse-debug.patch
@@ -1,8 +1,8 @@
-From 86906513b2597a79c26b72a6a9dc0ecf8b0ce1ed Mon Sep 17 00:00:00 2001
+From 0b992146abb735d42afa9f2fa62c077dd09879f2 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
+Subject: [PATCH 1019/1041] mtk: 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.
@@ -15,21 +15,22 @@
 
 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/mcu.c         |   8 ++++
  mt7996/mt7996.h      |   6 +++
  mt7996/mtk_debugfs.c |  82 ++++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.c     | 111 +++++++++++++++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.h     |  56 ++++++++++++++++++++++
- 7 files changed, 267 insertions(+)
+ 7 files changed, 270 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 42eb64c..e904ebc 100644
+index fefa2a0c..b657ef39 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1031,6 +1031,7 @@ enum {
+@@ -1029,6 +1029,7 @@ enum {
  	MCU_UNI_EVENT_BSS_BEACON_LOSS = 0x0c,
  	MCU_UNI_EVENT_SCAN_DONE = 0x0e,
  	MCU_UNI_EVENT_RDD_REPORT = 0x11,
@@ -38,7 +39,7 @@
  	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
+index 2042edd6..c1776aeb 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -6,6 +6,9 @@
@@ -62,26 +63,29 @@
  					   !dev->dbg.sku_disable);
  #else
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 722c435..2dbec1e 100644
+index 9331abb5..718a4f8d 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);
+@@ -712,6 +712,14 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	case MCU_UNI_EVENT_WED_RRO:
+ 		mt7996_mcu_wed_rro_event(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;
++	case MCU_UNI_EVENT_THERMAL:
++		mt7996_mcu_rx_thermal_notify(dev, skb);
++		break;
+ #ifdef CONFIG_NL80211_TESTMODE
+ 	case MCU_UNI_EVENT_TESTMODE_CTRL:
+ 		mt7996_tm_rf_test_event(dev, skb);
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 8fd29d7..1fac783 100644
+index 130e9b37..385f7218 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -306,6 +306,10 @@ struct mt7996_phy {
+@@ -351,6 +351,10 @@ struct mt7996_phy {
  	spinlock_t amnt_lock;
  	struct mt7996_air_monitor_ctrl amnt_ctrl;
  #endif
@@ -92,20 +96,20 @@
  };
  
  struct mt7996_dev {
-@@ -763,6 +767,8 @@ enum edcca_bw_id {
- 
+@@ -799,6 +803,8 @@ enum edcca_bw_id {
  #ifdef CONFIG_MTK_DEBUG
  int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
+ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
 +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
+index fe6492ab..6229739b 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)
+@@ -2681,6 +2681,83 @@ static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
  	return 0;
  }
  
@@ -189,9 +193,9 @@
  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)
- 
+@@ -2759,6 +2836,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("scs_enable", 0200, dir, phy, &fops_scs_enable);
  
 +	debugfs_create_file("sr_enable", 0600, dir, phy, &fops_sr_enable);
 +	debugfs_create_file("sr_enhanced_enable", 0600, dir, phy, &fops_sr_enhanced_enable);
@@ -202,10 +206,10 @@
  }
  
 diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
-index 048c534..3256de7 100644
+index 5c54d02c..dbdf8d80 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)
+@@ -146,4 +146,115 @@ int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set)
  	return 0;
  }
  
@@ -322,10 +326,10 @@
 +}
  #endif
 diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
-index 9c0db87..a5bdb88 100644
+index 1137fe5d..cc2de8f4 100644
 --- a/mt7996/mtk_mcu.h
 +++ b/mt7996/mtk_mcu.h
-@@ -104,6 +104,62 @@ enum {
+@@ -108,6 +108,62 @@ enum {
  	EDCCA_JAPAN = 3
  };
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
similarity index 62%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
index ac60aa8..5f2b377 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch
@@ -1,24 +1,24 @@
-From d7337c25e774ed96fc8f6d1390321bfc2dcac545 Mon Sep 17 00:00:00 2001
+From 135efc5c74d7ffdb671e7a8ffe32e18879251119 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
+Subject: [PATCH 1020/1041] mtk: 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
+index b92d7fe9..618c1f40 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)
+@@ -1032,8 +1032,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)
+ 	if (is_8023) {
  		fc = IEEE80211_FTYPE_DATA |
 -- 
 2.18.0
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch
deleted file mode 100644
index f7596bb..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1020-wifi-mt76-mt7996-Fix-incorrect-UWTBL_LEN_IN_DW-param.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-mtk-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-w.patch
similarity index 84%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-mtk-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-w.patch
index 9fbc586..169f6e0 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-worka.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1021-mtk-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-w.patch
@@ -1,8 +1,8 @@
-From b69722554a27e8c13612f62c9b9cf8651a30bd8f Mon Sep 17 00:00:00 2001
+From 4dac1d1c289eccead02ec6d942aaa9d28929c484 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
+Subject: [PATCH 1021/1041] mtk: wifi: mt76: mt7996: add eagle iFEM HWITS ZWDFS
+ SW workaround
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
@@ -12,10 +12,10 @@
  3 files changed, 60 insertions(+), 5 deletions(-)
 
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 35f8fee..d27275a 100644
+index c1776aeb..36894828 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -1413,6 +1413,54 @@ mt7996_twt_teardown_request(struct ieee80211_hw *hw,
+@@ -1431,6 +1431,54 @@ mt7996_twt_teardown_request(struct ieee80211_hw *hw,
  	mutex_unlock(&dev->mt76.mutex);
  }
  
@@ -70,7 +70,7 @@
  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,
+@@ -1439,6 +1487,7 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
  	struct mt7996_dev *dev = phy->dev;
  	int ret = -EINVAL;
  	bool running;
@@ -78,7 +78,7 @@
  
  	mutex_lock(&dev->mt76.mutex);
  
-@@ -1433,13 +1482,14 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
+@@ -1451,13 +1500,14 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
  		goto out;
  	}
  
@@ -95,7 +95,7 @@
  		ret = mt7996_mcu_rdd_background_enable(phy, NULL);
  		if (ret)
  			goto out;
-@@ -1448,7 +1498,9 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
+@@ -1466,7 +1516,9 @@ mt7996_set_radar_background(struct ieee80211_hw *hw,
  			goto update_phy;
  	}
  
@@ -107,10 +107,10 @@
  		goto out;
  
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 2dbec1e..a4f3ed9 100644
+index 718a4f8d..689f4ec5 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)
+@@ -369,12 +369,14 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
  	if (!mphy)
  		return;
  
@@ -128,10 +128,10 @@
  }
  
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 1fac783..413fbf7 100644
+index 385f7218..5175c7fa 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -392,6 +392,7 @@ struct mt7996_dev {
+@@ -440,6 +440,7 @@ struct mt7996_dev {
  	bool testmode_enable;
  	bool bin_file_mode;
  	u8 eeprom_mode;
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-mtk-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_le.patch
similarity index 78%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-mtk-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_le.patch
index 63afb2c..9c8994c 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_led.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1022-mtk-wifi-mt76-mt7996-report-tx-and-rx-byte-to-tpt_le.patch
@@ -1,17 +1,18 @@
-From fd96728a963faf55b7daba46a78aa25ab0c5f147 Mon Sep 17 00:00:00 2001
+From 386da4814a8d8edd4071d0a98ac53402f18845fc 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
+Subject: [PATCH 1022/1041] mtk: 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
+index 689f4ec5..5683b3f5 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)
+@@ -522,6 +522,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;
@@ -20,7 +21,7 @@
  
  		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)
+@@ -541,11 +543,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
  			if (!wcid)
  				break;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-wifi-mt76-mt7996-support-dup-wtbl.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-mtk-wifi-mt76-mt7996-support-dup-wtbl.patch
similarity index 71%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-wifi-mt76-mt7996-support-dup-wtbl.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-mtk-wifi-mt76-mt7996-support-dup-wtbl.patch
index 12cdca3..fe7894a 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-wifi-mt76-mt7996-support-dup-wtbl.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1023-mtk-wifi-mt76-mt7996-support-dup-wtbl.patch
@@ -1,10 +1,9 @@
-From a0baa183c16552ec874141c62ce3c6346d24c684 Mon Sep 17 00:00:00 2001
+From ea760fad749d58a54d4bbd41528a60503aa56eef 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
+Subject: [PATCH 1023/1041] mtk: 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 +
@@ -12,23 +11,23 @@
  3 files changed, 25 insertions(+)
 
 diff --git a/mt7996/init.c b/mt7996/init.c
-index ad93927..4503482 100644
+index ab13021c..b3677e03 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);
+@@ -680,6 +680,7 @@ static void mt7996_init_work(struct work_struct *work)
+ 	mt7996_mcu_set_eeprom(dev);
+ 	mt7996_mac_init(dev);
  	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
+index 5175c7fa..087ab526 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);
+@@ -806,6 +806,7 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
+ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
  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);
@@ -36,10 +35,10 @@
  
  #ifdef CONFIG_NET_MEDIATEK_SOC_WED
 diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
-index 3256de7..149694c 100644
+index dbdf8d80..ea4e5bf2 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)
+@@ -257,4 +257,27 @@ void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb)
  			 le16_to_cpu(event->basic.tag));
  	}
  }
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-mtk-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
similarity index 94%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-mtk-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
index 354e553..eb32e88 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1024-mtk-wifi-mt76-mt7996-add-ibf-control-vendor-cmd.patch
@@ -1,7 +1,7 @@
-From b5d139f32d6f4f6476b82d59af7a96a1f57858a9 Mon Sep 17 00:00:00 2001
+From 4d89751738af129e90d9c77fd72308decce2fbfc 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
+Subject: [PATCH 1024/1041] mtk: wifi: mt76: mt7996: add ibf control vendor cmd
 
 Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
 ---
@@ -10,7 +10,7 @@
  2 files changed, 88 insertions(+)
 
 diff --git a/mt7996/vendor.c b/mt7996/vendor.c
-index 9f333d0..dae3260 100644
+index 9f333d0e..dae3260a 100644
 --- a/mt7996/vendor.c
 +++ b/mt7996/vendor.c
 @@ -60,6 +60,11 @@ edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
@@ -100,7 +100,7 @@
  
  void mt7996_vendor_register(struct mt7996_phy *phy)
 diff --git a/mt7996/vendor.h b/mt7996/vendor.h
-index 4465bc9..49f46f2 100644
+index 4465bc9d..49f46f25 100644
 --- a/mt7996/vendor.h
 +++ b/mt7996/vendor.h
 @@ -7,6 +7,7 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-mtk-wifi-mt76-try-more-times-when-send-message-timeo.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-mtk-wifi-mt76-try-more-times-when-send-message-timeo.patch
new file mode 100644
index 0000000..a9be456
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1025-mtk-wifi-mt76-try-more-times-when-send-message-timeo.patch
@@ -0,0 +1,231 @@
+From 2e5df04c0677add9e853c65b619bacffbfd10cf6 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Nov 2023 11:10:10 +0800
+Subject: [PATCH 1025/1041] mtk: wifi: mt76: try more times when send message
+ timeout.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ dma.c        |  7 ++++--
+ mcu.c        | 65 ++++++++++++++++++++++++++++++++++++----------------
+ mt7996/mac.c | 49 ++++++++++-----------------------------
+ 3 files changed, 62 insertions(+), 59 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 12f0e2fd..be8e2aaa 100644
+--- a/dma.c
++++ b/dma.c
+@@ -506,9 +506,12 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+ {
+ 	struct mt76_queue_buf buf = {};
+ 	dma_addr_t addr;
++	int ret = -ENOMEM;
+ 
+-	if (test_bit(MT76_MCU_RESET, &dev->phy.state))
++	if (test_bit(MT76_MCU_RESET, &dev->phy.state)) {
++		ret = -EAGAIN;
+ 		goto error;
++	}
+ 
+ 	if (q->queued + 1 >= q->ndesc - 1)
+ 		goto error;
+@@ -530,7 +533,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+ 
+ error:
+ 	dev_kfree_skb(skb);
+-	return -ENOMEM;
++	return ret;
+ }
+ 
+ static int
+diff --git a/mcu.c b/mcu.c
+index fa4b0544..2926f715 100644
+--- a/mcu.c
++++ b/mcu.c
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include "mt76.h"
++#include "mt76_connac.h"
+ #include <linux/moduleparam.h>
+ 
+ struct sk_buff *
+@@ -74,35 +75,59 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
+ 				  int cmd, bool wait_resp,
+ 				  struct sk_buff **ret_skb)
+ {
++#define MT76_MSG_MAX_RETRY_CNT 3
+ 	unsigned long expires;
+-	int ret, seq;
++	int ret, seq, retry_cnt;
++	struct sk_buff *skb_tmp;
++	bool retry = wait_resp && is_mt7996(dev);
+ 
+ 	if (ret_skb)
+ 		*ret_skb = NULL;
+ 
+ 	mutex_lock(&dev->mcu.mutex);
+-
+-	ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
+-	if (ret < 0)
+-		goto out;
+-
+-	if (!wait_resp) {
+-		ret = 0;
+-		goto out;
++	retry_cnt = retry ? MT76_MSG_MAX_RETRY_CNT : 1;
++	while (retry_cnt) {
++		skb_tmp = mt76_mcu_msg_alloc(dev, skb->data, skb->len);
++		if (!skb_tmp)
++			goto out;
++
++		if (retry && retry_cnt < MT76_MSG_MAX_RETRY_CNT) {
++			if (test_bit(MT76_MCU_RESET, &dev->phy.state))
++				usleep_range(200000, 500000);
++			dev_err(dev->dev, "send message %08x timeout, try again.\n", cmd);
++		}
++
++		ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb_tmp, cmd, &seq);
++		if (ret < 0 && ret != -EAGAIN)
++			goto out;
++
++		if (!wait_resp) {
++			ret = 0;
++			goto out;
++		}
++
++		expires = jiffies + dev->mcu.timeout;
++
++		do {
++			skb_tmp = mt76_mcu_get_response(dev, expires);
++			ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb_tmp, seq);
++			if (ret == -ETIMEDOUT)
++				break;
++
++			if (!ret && ret_skb)
++				*ret_skb = skb_tmp;
++			else
++				dev_kfree_skb(skb_tmp);
++
++			if (ret != -EAGAIN)
++				goto out;
++		} while (ret == -EAGAIN);
++
++		retry_cnt--;
+ 	}
+ 
+-	expires = jiffies + dev->mcu.timeout;
+-
+-	do {
+-		skb = mt76_mcu_get_response(dev, expires);
+-		ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq);
+-		if (!ret && ret_skb)
+-			*ret_skb = skb;
+-		else
+-			dev_kfree_skb(skb);
+-	} while (ret == -EAGAIN);
+-
+ out:
++	dev_kfree_skb(skb);
+ 	mutex_unlock(&dev->mcu.mutex);
+ 
+ 	return ret;
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 618c1f40..96627a58 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1662,18 +1662,6 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+ 			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
+ 	}
+ 
+-	set_bit(MT76_RESET, &dev->mphy.state);
+-	set_bit(MT76_MCU_RESET, &dev->mphy.state);
+-	wake_up(&dev->mt76.mcu.wait);
+-	if (phy2) {
+-		set_bit(MT76_RESET, &phy2->mt76->state);
+-		set_bit(MT76_MCU_RESET, &phy2->mt76->state);
+-	}
+-	if (phy3) {
+-		set_bit(MT76_RESET, &phy3->mt76->state);
+-		set_bit(MT76_MCU_RESET, &phy3->mt76->state);
+-	}
+-
+ 	/* lock/unlock all queues to ensure that no tx is pending */
+ 	mt76_txq_schedule_all(&dev->mphy);
+ 	if (phy2)
+@@ -1787,13 +1775,24 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ 	phy3 = mt7996_phy3(dev);
+ 	dev->recovery.hw_full_reset = true;
+ 
+-	wake_up(&dev->mt76.mcu.wait);
+ 	ieee80211_stop_queues(mt76_hw(dev));
+ 	if (phy2)
+ 		ieee80211_stop_queues(phy2->mt76->hw);
+ 	if (phy3)
+ 		ieee80211_stop_queues(phy3->mt76->hw);
+ 
++	set_bit(MT76_RESET, &dev->mphy.state);
++	set_bit(MT76_MCU_RESET, &dev->mphy.state);
++	wake_up(&dev->mt76.mcu.wait);
++	if (phy2) {
++		set_bit(MT76_RESET, &phy2->mt76->state);
++		set_bit(MT76_MCU_RESET, &phy2->mt76->state);
++	}
++	if (phy3) {
++		set_bit(MT76_RESET, &phy3->mt76->state);
++		set_bit(MT76_MCU_RESET, &phy3->mt76->state);
++	}
++
+ 	cancel_work_sync(&dev->wed_rro.work);
+ 	cancel_delayed_work_sync(&dev->mphy.mac_work);
+ 	if (phy2)
+@@ -1896,16 +1895,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	wake_up(&dev->mt76.mcu.wait);
+ 
+-	cancel_work_sync(&dev->wed_rro.work);
+-	cancel_delayed_work_sync(&dev->mphy.mac_work);
+-	if (phy2) {
+-		set_bit(MT76_RESET, &phy2->mt76->state);
+-		cancel_delayed_work_sync(&phy2->mt76->mac_work);
+-	}
+-	if (phy3) {
+-		set_bit(MT76_RESET, &phy3->mt76->state);
+-		cancel_delayed_work_sync(&phy3->mt76->mac_work);
+-	}
+ 	mt76_worker_disable(&dev->mt76.tx_worker);
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
+ 		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+@@ -1916,8 +1905,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	}
+ 	napi_disable(&dev->mt76.tx_napi);
+ 
+-	mutex_lock(&dev->mt76.mutex);
+-
+ 	mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
+ 
+ 	if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
+@@ -1990,20 +1977,8 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	if (phy3)
+ 		ieee80211_wake_queues(phy3->mt76->hw);
+ 
+-	mutex_unlock(&dev->mt76.mutex);
+-
+ 	mt7996_update_beacons(dev);
+ 
+-	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
+-				     MT7996_WATCHDOG_TIME);
+-	if (phy2)
+-		ieee80211_queue_delayed_work(phy2->mt76->hw,
+-					     &phy2->mt76->mac_work,
+-					     MT7996_WATCHDOG_TIME);
+-	if (phy3)
+-		ieee80211_queue_delayed_work(phy3->mt76->hw,
+-					     &phy3->mt76->mac_work,
+-					     MT7996_WATCHDOG_TIME);
+ 	dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
+ 		 wiphy_name(dev->mt76.hw->wiphy));
+ }
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-mtk-wifi-mt76-mt7996-add-SER-overlap-handle.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-mtk-wifi-mt76-mt7996-add-SER-overlap-handle.patch
new file mode 100644
index 0000000..5561e51
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1026-mtk-wifi-mt76-mt7996-add-SER-overlap-handle.patch
@@ -0,0 +1,95 @@
+From 4165fd47922164b4837bc5d247a82bca1a8e1b75 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Tue, 21 Nov 2023 09:55:46 +0800
+Subject: [PATCH 1026/1041] mtk: wifi: mt76: mt7996: add SER overlap handle
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mcu.c           | 3 ++-
+ mt7996/mac.c    | 8 ++++++++
+ mt7996/mcu.c    | 8 ++++++++
+ mt7996/mt7996.h | 2 ++
+ 4 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/mcu.c b/mcu.c
+index 2926f715..a7afa2d7 100644
+--- a/mcu.c
++++ b/mcu.c
+@@ -94,7 +94,8 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
+ 		if (retry && retry_cnt < MT76_MSG_MAX_RETRY_CNT) {
+ 			if (test_bit(MT76_MCU_RESET, &dev->phy.state))
+ 				usleep_range(200000, 500000);
+-			dev_err(dev->dev, "send message %08x timeout, try again.\n", cmd);
++			dev_err(dev->dev, "send message %08x timeout, try again(%d).\n",
++				cmd, (MT76_MSG_MAX_RETRY_CNT - retry_cnt));
+ 		}
+ 
+ 		ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb_tmp, cmd, &seq);
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 96627a58..22d7dc6d 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1876,6 +1876,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
+ 		return;
+ 
++	dev->recovery.l1_reset_last = dev->recovery.l1_reset;
+ 	dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
+ 		 wiphy_name(dev->mt76.hw->wiphy));
+ 
+@@ -1893,6 +1894,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);
++	if (phy2)
++		set_bit(MT76_RESET, &phy2->mt76->state);
++	if (phy3)
++		set_bit(MT76_RESET, &phy3->mt76->state);
+ 	wake_up(&dev->mt76.mcu.wait);
+ 
+ 	mt76_worker_disable(&dev->mt76.tx_worker);
+@@ -2107,6 +2112,9 @@ void mt7996_reset(struct mt7996_dev *dev)
+ 		return;
+ 	}
+ 
++	if ((READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
++		dev->recovery.l1_reset++;
++
+ 	queue_work(dev->mt76.wq, &dev->reset_work);
+ 	wake_up(&dev->reset_wait);
+ }
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 5683b3f5..726d2adf 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -246,6 +246,14 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
+ 	u32 val;
+ 	u8 seq;
+ 
++	if (dev->recovery.l1_reset_last != dev->recovery.l1_reset) {
++		dev_info(dev->mt76.dev,"\n%s L1 SER recovery overlap, drop message %08x.",
++			 wiphy_name(dev->mt76.hw->wiphy), cmd);
++
++		dev_kfree_skb(skb);
++		return -EPERM;
++	}
++
+ 	mdev->mcu.timeout = 20 * HZ;
+ 
+ 	seq = ++dev->mt76.mcu.msg_seq & 0xf;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 087ab526..71602b9b 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -391,6 +391,8 @@ struct mt7996_dev {
+ 	wait_queue_head_t reset_wait;
+ 	struct {
+ 		u32 state;
++		u32 l1_reset;
++		u32 l1_reset_last;
+ 		u32 wa_reset_count;
+ 		u32 wm_reset_count;
+ 		bool hw_full_reset:1;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-mtk-wifi-mt76-mt7996-kite-default-1-pcie-setting.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-mtk-wifi-mt76-mt7996-kite-default-1-pcie-setting.patch
new file mode 100644
index 0000000..95c0edf
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-mtk-wifi-mt76-mt7996-kite-default-1-pcie-setting.patch
@@ -0,0 +1,57 @@
+From c0b68dfc03ee90fde9ebacc07db8f3c186846dd5 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 13 Jul 2023 16:36:36 +0800
+Subject: [PATCH 1027/1041] mtk: wifi: mt76: mt7996: kite default 1-pcie
+ setting
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/pci.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 04056181..05830c01 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -11,6 +11,9 @@
+ #include "mac.h"
+ #include "../trace.h"
+ 
++static bool hif2_enable = false;
++module_param(hif2_enable, bool, 0644);
++
+ static LIST_HEAD(hif_list);
+ static DEFINE_SPINLOCK(hif_lock);
+ static u32 hif_idx;
+@@ -63,6 +66,9 @@ static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
+ {
+ 	hif_idx++;
+ 
++	if (!hif2_enable)
++		return NULL;
++
+ 	if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&
+ 	    !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))
+ 		return NULL;
+@@ -77,6 +83,9 @@ static int mt7996_pci_hif2_probe(struct pci_dev *pdev)
+ {
+ 	struct mt7996_hif *hif;
+ 
++	if (!hif2_enable)
++		return 0;
++
+ 	hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
+ 	if (!hif)
+ 		return -ENOMEM;
+@@ -101,6 +110,8 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 	int irq, hif2_irq, ret;
+ 	struct mt76_dev *mdev;
+ 
++	hif2_enable |= (id->device == 0x7990 || id->device == 0x7991);
++
+ 	ret = pcim_enable_device(pdev);
+ 	if (ret)
+ 		return ret;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch
deleted file mode 100644
index a555c23..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1027-wifi-mt76-mt7996-add-kite-fwdl-support.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-mtk-wifi-mt76-mt7996-add-debugfs-knob-for-rx_counter.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-mtk-wifi-mt76-mt7996-add-debugfs-knob-for-rx_counter.patch
new file mode 100644
index 0000000..5822e8c
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-mtk-wifi-mt76-mt7996-add-debugfs-knob-for-rx_counter.patch
@@ -0,0 +1,291 @@
+From 64832783fc40e4a4075c2ac3b9c78a81266ef988 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 28 Apr 2023 10:39:58 +0800
+Subject: [PATCH 1028/1041] mtk: wifi: mt76: mt7996: add debugfs knob for
+ rx_counters
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ agg-rx.c             |  8 ++++++++
+ mac80211.c           | 16 ++++++++++++++--
+ mt76.h               | 15 +++++++++++++++
+ mt7996/mac.c         | 18 +++++++++++++++---
+ mt7996/mtk_debugfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 94 insertions(+), 5 deletions(-)
+
+diff --git a/agg-rx.c b/agg-rx.c
+index 10cbd9e5..adb5a7d7 100644
+--- a/agg-rx.c
++++ b/agg-rx.c
+@@ -33,10 +33,13 @@ mt76_rx_aggr_release_frames(struct mt76_rx_tid *tid,
+ 			    struct sk_buff_head *frames,
+ 			    u16 head)
+ {
++	struct mt76_phy *phy = mt76_dev_phy(tid->dev, tid->band_idx);
+ 	int idx;
+ 
+ 	while (ieee80211_sn_less(tid->head, head)) {
+ 		idx = tid->head % tid->size;
++		if (!tid->reorder_buf[idx])
++			phy->rx_stats.rx_agg_miss++;
+ 		mt76_aggr_release(tid, frames, idx);
+ 	}
+ }
+@@ -151,6 +154,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
+ 	struct mt76_wcid *wcid = status->wcid;
+ 	struct ieee80211_sta *sta;
+ 	struct mt76_rx_tid *tid;
++	struct mt76_phy *phy;
+ 	bool sn_less;
+ 	u16 seqno, head, size, idx;
+ 	u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
+@@ -186,6 +190,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
+ 	head = tid->head;
+ 	seqno = status->seqno;
+ 	size = tid->size;
++	phy = mt76_dev_phy(tid->dev, tid->band_idx);
+ 	sn_less = ieee80211_sn_less(seqno, head);
+ 
+ 	if (!tid->started) {
+@@ -197,6 +202,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
+ 
+ 	if (sn_less) {
+ 		__skb_unlink(skb, frames);
++		phy->rx_stats.rx_dup_drop++;
+ 		dev_kfree_skb(skb);
+ 		goto out;
+ 	}
+@@ -223,6 +229,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
+ 
+ 	/* Discard if the current slot is already in use */
+ 	if (tid->reorder_buf[idx]) {
++		phy->rx_stats.rx_dup_drop++;
+ 		dev_kfree_skb(skb);
+ 		goto out;
+ 	}
+@@ -254,6 +261,7 @@ int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno,
+ 	tid->head = ssn;
+ 	tid->size = size;
+ 	tid->num = tidno;
++	tid->band_idx = wcid->phy_idx;
+ 	INIT_DELAYED_WORK(&tid->reorder_work, mt76_rx_aggr_reorder_work);
+ 	spin_lock_init(&tid->lock);
+ 
+diff --git a/mac80211.c b/mac80211.c
+index 87dcc8a3..45791f6e 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -784,6 +784,7 @@ static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
+ 		}
+ 
+ 		if (ether_addr_equal(skb->data + offset, rfc1042_header)) {
++			phy->rx_stats.rx_drop++;
+ 			dev_kfree_skb(skb);
+ 			return;
+ 		}
+@@ -1100,10 +1101,16 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
+ 
+ 	*sta = wcid_to_sta(mstat.wcid);
+ 	*hw = mt76_phy_hw(dev, mstat.phy_idx);
++
++	if ((mstat.flag & RX_FLAG_8023) || ieee80211_is_data_qos(hdr->frame_control)) {
++		struct mt76_phy *phy = mt76_dev_phy(dev, mstat.phy_idx);
++
++		phy->rx_stats.rx_mac80211++;
++	}
+ }
+ 
+ static void
+-mt76_check_ccmp_pn(struct sk_buff *skb)
++mt76_check_ccmp_pn(struct mt76_dev *dev, struct sk_buff *skb)
+ {
+ 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ 	struct mt76_wcid *wcid = status->wcid;
+@@ -1150,7 +1157,11 @@ skip_hdr_check:
+ 	ret = memcmp(status->iv, wcid->rx_key_pn[security_idx],
+ 		     sizeof(status->iv));
+ 	if (ret <= 0) {
++		struct mt76_phy *phy = mt76_dev_phy(dev, status->phy_idx);
++
++		phy->rx_stats.rx_pn_iv_error++;
+ 		status->flag |= RX_FLAG_ONLY_MONITOR;
++
+ 		return;
+ 	}
+ 
+@@ -1331,7 +1342,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
+ 	while ((skb = __skb_dequeue(frames)) != NULL) {
+ 		struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
+ 
+-		mt76_check_ccmp_pn(skb);
++		mt76_check_ccmp_pn(dev, skb);
+ 		skb_shinfo(skb)->frag_list = NULL;
+ 		mt76_rx_convert(dev, skb, &hw, &sta);
+ 		ieee80211_rx_list(hw, sta, skb, &list);
+@@ -1354,6 +1365,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
+ 	}
+ 
+ 	list_for_each_entry_safe(skb, tmp, &list, list) {
++		dev->rx_kernel++;
+ 		skb_list_del_init(skb);
+ 		napi_gro_receive(napi, skb);
+ 	}
+diff --git a/mt76.h b/mt76.h
+index 46fbc87e..9e8848f7 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -422,6 +422,7 @@ struct mt76_rx_tid {
+ 	struct rcu_head rcu_head;
+ 
+ 	struct mt76_dev *dev;
++	u8 band_idx;
+ 
+ 	spinlock_t lock;
+ 	struct delayed_work reorder_work;
+@@ -853,6 +854,19 @@ struct mt76_phy {
+ 		bool al;
+ 		u8 pin;
+ 	} leds;
++
++	struct {
++		u32 rx_mac80211;
++
++		u32 rx_drop;
++		u32 rx_rxd_drop;
++		u32 rx_dup_drop;
++		u32 rx_agg_miss;
++		u32 rx_icv_error;
++		u32 rx_fcs_error;
++		u32 rx_tkip_mic_error;
++		u32 rx_pn_iv_error;
++	} rx_stats;
+ };
+ 
+ struct mt76_dev {
+@@ -958,6 +972,7 @@ struct mt76_dev {
+ 	};
+ 
+ 	const char *bin_file_name;
++	u32 rx_kernel;
+ };
+ 
+ /* per-phy stats.  */
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 22d7dc6d..73c66e57 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -469,8 +469,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
+ 		return -EINVAL;
+ 
+ 	/* ICV error or CCMP/BIP/WPI MIC error */
+-	if (rxd1 & MT_RXD1_NORMAL_ICV_ERR)
++	if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) {
++		mphy->rx_stats.rx_icv_error++;
+ 		status->flag |= RX_FLAG_ONLY_MONITOR;
++	}
+ 
+ 	unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
+ 	idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
+@@ -501,11 +503,15 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
+ 	    !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
+ 		skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 
+-	if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)
++	if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) {
++		mphy->rx_stats.rx_fcs_error++;
+ 		status->flag |= RX_FLAG_FAILED_FCS_CRC;
++	}
+ 
+-	if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
++	if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) {
++		mphy->rx_stats.rx_tkip_mic_error++;
+ 		status->flag |= RX_FLAG_MMIC_ERROR;
++	}
+ 
+ 	if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
+ 	    !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) {
+@@ -1414,8 +1420,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 			 struct sk_buff *skb, u32 *info)
+ {
+ 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++	struct mt76_phy *phy;
+ 	__le32 *rxd = (__le32 *)skb->data;
+ 	__le32 *end = (__le32 *)&skb->data[skb->len];
++	u8 band_idx;
+ 	enum rx_pkt_type type;
+ 
+ 	type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
+@@ -1457,6 +1465,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 		}
+ 		fallthrough;
+ 	default:
++		band_idx = le32_get_bits(rxd[1], MT_RXD1_NORMAL_BAND_IDX);
++		phy = mt76_dev_phy(mdev, band_idx);
++		if (likely(phy))
++			phy->rx_stats.rx_rxd_drop++;
+ 		dev_kfree_skb(skb);
+ 		break;
+ 	}
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 6229739b..e1689605 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2758,6 +2758,46 @@ mt7996_sr_scene_cond_show(struct seq_file *file, void *data)
+ }
+ DEFINE_SHOW_ATTRIBUTE(mt7996_sr_scene_cond);
+ 
++static int mt7996_rx_counters(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	u32 rx_mac80211 = 0;
++	int i = 0;
++
++	for (i = 0; i < __MT_MAX_BAND; i++) {
++		struct mt76_phy *phy = mt76_dev_phy(&dev->mt76, i);
++
++		if (!phy)
++			continue;
++
++		seq_printf(s, "\n==========PHY%d==========\n", i);
++
++#define SEQ_PRINT(_str, _rx_param) do {					\
++		seq_printf(s, _str"\n", phy->rx_stats._rx_param);	\
++	} while (0)
++
++		SEQ_PRINT("Rx to mac80211: %u", rx_mac80211);
++		SEQ_PRINT("Rx drop: %u", rx_drop);
++		SEQ_PRINT("Rx drop due to RXD type error: %u", rx_rxd_drop);
++		SEQ_PRINT("Rx duplicated drop: %u", rx_dup_drop);
++		SEQ_PRINT("Rx agg miss: %u", rx_agg_miss);
++		SEQ_PRINT("Rx ICV error: %u", rx_icv_error);
++		SEQ_PRINT("Rx FCS error: %u", rx_fcs_error);
++		SEQ_PRINT("Rx TKIP MIC error: %u", rx_tkip_mic_error);
++		SEQ_PRINT("Rx PN/IV error: %u", rx_pn_iv_error);
++#undef SEQ_PRINT
++
++		rx_mac80211 += phy->rx_stats.rx_mac80211;
++	}
++
++	seq_printf(s, "\n==========SUM==========\n");
++	seq_printf(s, "Rx to kernel: %u\n", dev->mt76.rx_kernel);
++	seq_printf(s, "Rx to mac80211: %u\n", rx_mac80211);
++
++
++	return 0;
++}
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2821,6 +2861,8 @@ 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);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "rx_counters", dir,
++				    mt7996_rx_counters);
+ 	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);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch
deleted file mode 100644
index 3556945..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1028-wifi-mt76-mt7996-add-kite-eeprom-load-support.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-mtk-wifi-mt76-mt7996-add-three-wire-pta-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-mtk-wifi-mt76-mt7996-add-three-wire-pta-support.patch
new file mode 100644
index 0000000..9902ccb
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-mtk-wifi-mt76-mt7996-add-three-wire-pta-support.patch
@@ -0,0 +1,133 @@
+From 1f4de166ff558ddc2803ce0661ac212dd8e7ffe2 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Tue, 24 Oct 2023 15:59:18 +0800
+Subject: [PATCH 1029/1041] mtk: wifi: mt76: mt7996: add three wire pta support
+
+three wire enable bit 0 & 1 for EXT0 & EXT1, respectively
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac_mcu.h |  1 +
+ mt7996/vendor.c   | 49 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h   | 12 ++++++++++++
+ 3 files changed, 62 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index b657ef39..615c42b1 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1274,6 +1274,7 @@ enum {
+ 	MCU_UNI_CMD_PER_STA_INFO = 0x6d,
+ 	MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
+ 	MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
++	MCU_UNI_CMD_PTA_3WIRE_CTRL = 0x78,
+ };
+ 
+ enum {
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index dae3260a..9ba6f00a 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
++three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
++	[MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.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 },
+@@ -561,6 +566,39 @@ mt7996_vendor_edcca_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return EDCCA_MAX_BW_NUM;
+ }
+ 
++static int mt7996_vendor_3wire_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
++				    const void *data, int data_len)
++{
++#define UNI_3WIRE_EXT_EN	0
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct mt7996_dev *dev = mt7996_hw_dev(hw);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL];
++	struct {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 three_wire_mode;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_3WIRE_EXT_EN),
++		.len = cpu_to_le16(sizeof(req) - 4),
++	};
++	int err;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_3WIRE_CTRL_MAX, data, data_len,
++			three_wire_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (!tb[MTK_VENDOR_ATTR_3WIRE_CTRL_MODE])
++		return -EINVAL;
++
++	req.three_wire_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_3WIRE_CTRL_MODE]);
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PTA_3WIRE_CTRL), &req,
++				 sizeof(req), false);
++}
++
+ static int mt7996_vendor_ibf_ctrl(struct wiphy *wiphy,
+ 				  struct wireless_dev *wdev,
+ 				  const void *data,
+@@ -657,6 +695,17 @@ 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_3WIRE_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_3wire_ctrl,
++		.policy = three_wire_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_3WIRE_CTRL_MAX,
++	},
+ 	{
+ 		.info = {
+ 			.vendor_id = MTK_NL80211_VENDOR_ID,
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 49f46f25..29ccc050 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_3WIRE_CTRL = 0xc8,
+ 	MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
+ 	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+@@ -43,6 +44,17 @@ enum mtk_vendor_attr_edcca_dump {
+ 		NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
+ };
+ 
++enum mtk_vendor_attr_3wire_ctrl {
++	MTK_VENDOR_ATTR_3WIRE_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_3WIRE_CTRL_MODE,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL,
++	MTK_VENDOR_ATTR_3WIRE_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL - 1
++};
++
+ enum mtk_vendor_attr_mu_ctrl {
+ 	MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch
deleted file mode 100644
index 8b8119a..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1029-wifi-mt76-mt7996-add-kite-fw-default-bin-for-differe.patch
+++ /dev/null
@@ -1,128 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch
new file mode 100644
index 0000000..3048405
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch
@@ -0,0 +1,1204 @@
+From 05cf83b4947264a8afca95116afd98cb4519a9d5 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Tue, 3 Jan 2023 09:42:07 +0800
+Subject: [PATCH 1030/1041] mtk: wifi: mt76: mt7996: support BF/MIMO debug
+ commands
+
+This commit includes the following commands:
+1. starec_bf_read
+2. txbf_snd_info: start/stop sounding and set sounding period
+3. fbkRptInfo
+4. fix muru rate
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+fix the wrong wlan_idx for user3
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/mcu.c         |   5 +
+ mt7996/mcu.h         |   4 +
+ mt7996/mt7996.h      |   5 +
+ mt7996/mtk_debugfs.c | 120 +++++++++
+ mt7996/mtk_mcu.c     | 626 +++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h     | 342 +++++++++++++++++++++++
+ 6 files changed, 1102 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 726d2adf..d3dab186 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -741,6 +741,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	case MCU_UNI_EVENT_TESTMODE_CTRL:
+ 		mt7996_tm_rf_test_event(dev, skb);
+ 		break;
++#endif
++#if defined CONFIG_NL80211_TESTMODE || defined CONFIG_MTK_DEBUG
++	case MCU_UNI_EVENT_BF:
++		mt7996_mcu_rx_bf_event(dev, skb);
++		break;
+ #endif
+ 	default:
+ 		break;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 34fdfb26..347893c8 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -770,8 +770,12 @@ enum {
+ 
+ enum {
+ 	BF_SOUNDING_ON = 1,
++	BF_PFMU_TAG_READ = 5,
++	BF_STA_REC_READ = 11,
+ 	BF_HW_EN_UPDATE = 17,
+ 	BF_MOD_EN_CTRL = 20,
++	BF_FBRPT_DBG_INFO_READ = 23,
++	BF_TXSND_INFO = 24,
+ };
+ 
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 71602b9b..a321e8e8 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -809,6 +809,11 @@ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
+ 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);
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx);
++void mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb);
++int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val);
++int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para);
++int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para);
+ #endif
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index e1689605..938da645 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2798,6 +2798,117 @@ static int mt7996_rx_counters(struct seq_file *s, void *data)
+ 	return 0;
+ }
+ 
++static int
++mt7996_starec_bf_read_set(void *data, u64 wlan_idx)
++{
++	struct mt7996_phy *phy = data;
++
++	return mt7996_mcu_set_txbf_internal(phy, BF_STA_REC_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_starec_bf_read, NULL,
++			 mt7996_starec_bf_read_set, "%lld\n");
++
++static ssize_t
++mt7996_bf_txsnd_info_set(struct file *file,
++			 const char __user *user_buf,
++			 size_t count, loff_t *ppos)
++{
++	struct mt7996_phy *phy = file->private_data;
++	char buf[40];
++	int ret;
++
++	if (count >= sizeof(buf))
++		return -EINVAL;
++
++	if (copy_from_user(buf, user_buf, count))
++		return -EFAULT;
++
++	if (count && buf[count - 1] == '\n')
++		buf[count - 1] = '\0';
++	else
++		buf[count] = '\0';
++
++	ret = mt7996_mcu_set_txbf_snd_info(phy, buf);
++
++	if (ret) return -EFAULT;
++
++	return count;
++}
++
++static const struct file_operations fops_bf_txsnd_info = {
++	.write = mt7996_bf_txsnd_info_set,
++	.read = NULL,
++	.open = simple_open,
++	.llseek = default_llseek,
++};
++
++static int
++mt7996_bf_fbk_rpt_set(void *data, u64 wlan_idx)
++{
++	struct mt7996_phy *phy = data;
++
++	return mt7996_mcu_set_txbf_internal(phy, BF_FBRPT_DBG_INFO_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_fbk_rpt, NULL,
++			 mt7996_bf_fbk_rpt_set, "%lld\n");
++
++static int
++mt7996_bf_pfmu_tag_read_set(void *data, u64 wlan_idx)
++{
++	struct mt7996_phy *phy = data;
++
++	return mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_pfmu_tag_read, NULL,
++			 mt7996_bf_pfmu_tag_read_set, "%lld\n");
++
++static int
++mt7996_muru_fixed_rate_set(void *data, u64 val)
++{
++	struct mt7996_dev *dev = data;
++
++	return mt7996_mcu_set_muru_fixed_rate_enable(dev, UNI_CMD_MURU_FIXED_RATE_CTRL,
++						     val);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_fixed_rate_enable, NULL,
++			 mt7996_muru_fixed_rate_set, "%lld\n");
++
++static ssize_t
++mt7996_muru_fixed_rate_parameter_set(struct file *file,
++				     const char __user *user_buf,
++				     size_t count, loff_t *ppos)
++{
++	struct mt7996_dev *dev = file->private_data;
++	char buf[40];
++	int ret;
++
++	if (count >= sizeof(buf))
++		return -EINVAL;
++
++	if (copy_from_user(buf, user_buf, count))
++		return -EFAULT;
++
++	if (count && buf[count - 1] == '\n')
++		buf[count - 1] = '\0';
++	else
++		buf[count] = '\0';
++
++
++	ret = mt7996_mcu_set_muru_fixed_rate_parameter(dev, UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++						       buf);
++
++	if (ret) return -EFAULT;
++
++	return count;
++}
++
++static const struct file_operations fops_muru_fixed_group_rate = {
++	.write = mt7996_muru_fixed_rate_parameter_set,
++	.read = NULL,
++	.open = simple_open,
++	.llseek = default_llseek,
++};
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2883,6 +2994,15 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 	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);
+ 
++	debugfs_create_file("muru_fixed_rate_enable", 0600, dir, dev,
++			    &fops_muru_fixed_rate_enable);
++	debugfs_create_file("muru_fixed_group_rate", 0600, dir, dev,
++			    &fops_muru_fixed_group_rate);
++	debugfs_create_file("bf_txsnd_info", 0600, dir, phy, &fops_bf_txsnd_info);
++	debugfs_create_file("bf_starec_read", 0600, dir, phy, &fops_starec_bf_read);
++	debugfs_create_file("bf_fbk_rpt", 0600, dir, phy, &fops_bf_fbk_rpt);
++	debugfs_create_file("pfmu_tag_read", 0600, dir, phy, &fops_bf_pfmu_tag_read);
++
+ 	return 0;
+ }
+ 
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index ea4e5bf2..67419cd9 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -280,4 +280,630 @@ int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev)
+ 	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(CHIP_CONFIG), &req,
+ 				 sizeof(req), true);
+ }
++
++static struct tlv *
++__mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len)
++{
++	struct tlv *ptlv, tlv = {
++		.tag = cpu_to_le16(tag),
++		.len = cpu_to_le16(len),
++	};
++
++	ptlv = skb_put(skb, len);
++	memcpy(ptlv, &tlv, sizeof(tlv));
++
++	return ptlv;
++}
++
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx)
++{
++	struct mt7996_dev *dev = phy->dev;
++#define MT7996_MTK_BF_MAX_SIZE	sizeof(struct bf_starec_read)
++	struct uni_header hdr;
++	struct sk_buff *skb;
++	struct tlv *tlv;
++	int len = sizeof(hdr) + MT7996_MTK_BF_MAX_SIZE;
++
++	memset(&hdr, 0, sizeof(hdr));
++
++	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len);
++	if (!skb)
++		return -ENOMEM;
++
++	skb_put_data(skb, &hdr, sizeof(hdr));
++
++	switch (action) {
++	case BF_PFMU_TAG_READ: {
++		struct bf_pfmu_tag *req;
++
++		tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++		req = (struct bf_pfmu_tag *)tlv;
++#define BFER 1
++		req->pfmu_id = idx;
++		req->bfer = BFER;
++		req->band_idx = phy->mt76->band_idx;
++		break;
++	}
++	case BF_STA_REC_READ: {
++		struct bf_starec_read *req;
++
++		tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++		req = (struct bf_starec_read *)tlv;
++		req->wlan_idx = idx;
++		break;
++	}
++	case BF_FBRPT_DBG_INFO_READ: {
++		struct bf_fbk_rpt_info *req;
++
++		if (idx != 0) {
++			dev_info(dev->mt76.dev, "Invalid input");
++			return 0;
++		}
++
++		tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++		req = (struct bf_fbk_rpt_info *)tlv;
++		req->action = idx;
++		req->band_idx = phy->mt76->band_idx;
++		break;
++	}
++	default:
++		return -EINVAL;
++	}
++
++	return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, MCU_WM_UNI_CMD(BF), false);
++}
++
++int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para)
++{
++	char *buf = (char *)para;
++	__le16 input[5] = {0};
++	u8 recv_arg = 0;
++	struct bf_txsnd_info *req;
++	struct uni_header hdr;
++	struct sk_buff *skb;
++	struct tlv *tlv;
++	int len = sizeof(hdr) + MT7996_MTK_BF_MAX_SIZE;
++
++	memset(&hdr, 0, sizeof(hdr));
++
++	skb = mt76_mcu_msg_alloc(&phy->dev->mt76, NULL, len);
++	if (!skb)
++		return -ENOMEM;
++
++	skb_put_data(skb, &hdr, sizeof(hdr));
++
++	recv_arg = sscanf(buf, "%hx:%hx:%hx:%hx:%hx", &input[0], &input[1], &input[2],
++						      &input[3], &input[4]);
++
++	if (!recv_arg)
++		return -EINVAL;
++
++	tlv = __mt7996_mcu_add_uni_tlv(skb, BF_TXSND_INFO, sizeof(*req));
++	req = (struct bf_txsnd_info *)tlv;
++	req->action = input[0];
++
++	switch (req->action) {
++	case BF_SND_READ_INFO: {
++		req->read_clr = input[1];
++		break;
++	}
++	case BF_SND_CFG_OPT: {
++		req->vht_opt = input[1];
++		req->he_opt = input[2];
++		req->glo_opt = input[3];
++		break;
++	}
++	case BF_SND_CFG_INTV: {
++		req->wlan_idx = input[1];
++		req->snd_intv = input[2];
++		break;
++	}
++	case BF_SND_STA_STOP: {
++		req->wlan_idx = input[1];
++		req->snd_stop = input[2];
++		break;
++	}
++	case BF_SND_CFG_MAX_STA: {
++		req->max_snd_stas = input[1];
++		break;
++	}
++	case BF_SND_CFG_BFRP: {
++		req->man = input[1];
++		req->tx_time = input[2];
++		req->mcs = input[3];
++		req->ldpc = input[4];
++		break;
++	}
++	case BF_SND_CFG_INF: {
++		req->inf = input[1];
++		break;
++	}
++	case BF_SND_CFG_TXOP_SND: {
++		req->man = input[1];
++		req->ac_queue = input[2];
++		req->sxn_protect = input[3];
++		req->direct_fbk = input[4];
++		break;
++	}
++	default:
++		return -EINVAL;
++	}
++
++	return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, MCU_WM_UNI_CMD(BF), false);
++}
++
++void
++mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++#define HE_MODE 3
++	struct mt7996_mcu_bf_basic_event *event;
++
++	event = (struct mt7996_mcu_bf_basic_event *)skb->data;
++
++	dev_info(dev->mt76.dev, " bf_event tag = %d\n", event->tag);
++
++	switch (event->tag) {
++	case UNI_EVENT_BF_PFMU_TAG: {
++
++		struct mt7996_pfmu_tag_event *tag;
++		u32 *raw_t1, *raw_t2;
++
++		tag = (struct mt7996_pfmu_tag_event *) skb->data;
++
++		raw_t1 = (u32 *)&tag->t1;
++		raw_t2 = (u32 *)&tag->t2;
++
++		dev_info(dev->mt76.dev, "=================== TXBf Profile Tag1 Info ==================\n");
++		dev_info(dev->mt76.dev,
++			 "DW0 = 0x%08x, DW1 = 0x%08x, DW2 = 0x%08x\n",
++			 raw_t1[0], raw_t1[1], raw_t1[2]);
++		dev_info(dev->mt76.dev,
++			 "DW4 = 0x%08x, DW5 = 0x%08x, DW6 = 0x%08x\n\n",
++			 raw_t1[3], raw_t1[4], raw_t1[5]);
++		dev_info(dev->mt76.dev, "PFMU ID = %d              Invalid status = %d\n",
++			 tag->t1.pfmu_idx, tag->t1.invalid_prof);
++		dev_info(dev->mt76.dev, "iBf/eBf = %d\n\n", tag->t1.ebf);
++		dev_info(dev->mt76.dev, "DBW   = %d\n", tag->t1.data_bw);
++		dev_info(dev->mt76.dev, "SU/MU = %d\n", tag->t1.is_mu);
++		dev_info(dev->mt76.dev,
++			 "nrow = %d, ncol = %d, ng = %d, LM = %d, CodeBook = %d MobCalEn = %d\n",
++			 tag->t1.nr, tag->t1.nc, tag->t1.ngroup, tag->t1.lm, tag->t1.codebook,
++			 tag->t1.mob_cal_en);
++
++		if (tag->t1.lm <= HE_MODE) {
++			dev_info(dev->mt76.dev, "RU start = %d, RU end = %d\n",
++				 tag->t1.field.ru_start_id, tag->t1.field.ru_end_id);
++		} else {
++			dev_info(dev->mt76.dev, "PartialBW = %d\n",
++				 tag->t1.bw_info.partial_bw_info);
++		}
++
++		dev_info(dev->mt76.dev, "Mem Col1 = %d, Mem Row1 = %d, Mem Col2 = %d, Mem Row2 = %d\n",
++			 tag->t1.col_id1, tag->t1.row_id1, tag->t1.col_id2, tag->t1.row_id2);
++		dev_info(dev->mt76.dev, "Mem Col3 = %d, Mem Row3 = %d, Mem Col4 = %d, Mem Row4 = %d\n\n",
++			 tag->t1.col_id3, tag->t1.row_id3, tag->t1.col_id4, tag->t1.row_id4);
++		dev_info(dev->mt76.dev,
++			 "STS0_SNR = 0x%02x, STS1_SNR = 0x%02x, STS2_SNR = 0x%02x, STS3_SNR = 0x%02x\n",
++			 tag->t1.snr_sts0, tag->t1.snr_sts1, tag->t1.snr_sts2, tag->t1.snr_sts3);
++		dev_info(dev->mt76.dev,
++			 "STS4_SNR = 0x%02x, STS5_SNR = 0x%02x, STS6_SNR = 0x%02x, STS7_SNR = 0x%02x\n",
++			 tag->t1.snr_sts4, tag->t1.snr_sts5, tag->t1.snr_sts6, tag->t1.snr_sts7);
++		dev_info(dev->mt76.dev, "=============================================================\n");
++
++		dev_info(dev->mt76.dev, "=================== TXBf Profile Tag2 Info ==================\n");
++		dev_info(dev->mt76.dev,
++			 "DW0 = 0x%08x, DW1 = 0x%08x, DW2 = 0x%08x\n",
++			 raw_t2[0], raw_t2[1], raw_t2[2]);
++		dev_info(dev->mt76.dev,
++			 "DW3 = 0x%08x, DW4 = 0x%08x, DW5 = 0x%08x\n\n",
++			 raw_t2[3], raw_t2[4], raw_t2[5]);
++		dev_info(dev->mt76.dev, "Smart antenna ID = 0x%x,  SE index = %d\n",
++			 tag->t2.smart_ant, tag->t2.se_idx);
++		dev_info(dev->mt76.dev, "Timeout = 0x%x\n", tag->t2.ibf_timeout);
++		dev_info(dev->mt76.dev, "Desired BW = %d, Desired Ncol = %d, Desired Nrow = %d\n",
++			 tag->t2.ibf_data_bw, tag->t2.ibf_nc, tag->t2.ibf_nr);
++		dev_info(dev->mt76.dev, "Desired RU Allocation = %d\n", tag->t2.ibf_ru);
++		dev_info(dev->mt76.dev, "Mobility DeltaT = %d, Mobility LQ = %d\n",
++			 tag->t2.mob_delta_t, tag->t2.mob_lq_result);
++		dev_info(dev->mt76.dev, "=============================================================\n");
++		break;
++	}
++	case UNI_EVENT_BF_STAREC: {
++
++		struct mt7996_mcu_bf_starec_read *r;
++
++		r = (struct mt7996_mcu_bf_starec_read *)skb->data;
++		dev_info(dev->mt76.dev, "=================== BF StaRec ===================\n"
++					"rStaRecBf.u2PfmuId      = %d\n"
++					"rStaRecBf.fgSU_MU       = %d\n"
++					"rStaRecBf.u1TxBfCap     = %d\n"
++					"rStaRecBf.ucSoundingPhy = %d\n"
++					"rStaRecBf.ucNdpaRate    = %d\n"
++					"rStaRecBf.ucNdpRate     = %d\n"
++					"rStaRecBf.ucReptPollRate= %d\n"
++					"rStaRecBf.ucTxMode      = %d\n"
++					"rStaRecBf.ucNc          = %d\n"
++					"rStaRecBf.ucNr          = %d\n"
++					"rStaRecBf.ucCBW         = %d\n"
++					"rStaRecBf.ucMemRequire20M = %d\n"
++					"rStaRecBf.ucMemRow0     = %d\n"
++					"rStaRecBf.ucMemCol0     = %d\n"
++					"rStaRecBf.ucMemRow1     = %d\n"
++					"rStaRecBf.ucMemCol1     = %d\n"
++					"rStaRecBf.ucMemRow2     = %d\n"
++					"rStaRecBf.ucMemCol2     = %d\n"
++					"rStaRecBf.ucMemRow3     = %d\n"
++					"rStaRecBf.ucMemCol3     = %d\n",
++					r->pfmu_id,
++					r->is_su_mu,
++					r->txbf_cap,
++					r->sounding_phy,
++					r->ndpa_rate,
++					r->ndp_rate,
++					r->rpt_poll_rate,
++					r->tx_mode,
++					r->nc,
++					r->nr,
++					r->bw,
++					r->mem_require_20m,
++					r->mem_row0,
++					r->mem_col0,
++					r->mem_row1,
++					r->mem_col1,
++					r->mem_row2,
++					r->mem_col2,
++					r->mem_row3,
++					r->mem_col3);
++
++		dev_info(dev->mt76.dev, "rStaRecBf.u2SmartAnt    = 0x%x\n"
++					"rStaRecBf.ucSEIdx       = %d\n"
++					"rStaRecBf.uciBfTimeOut  = 0x%x\n"
++					"rStaRecBf.uciBfDBW      = %d\n"
++					"rStaRecBf.uciBfNcol     = %d\n"
++					"rStaRecBf.uciBfNrow     = %d\n"
++					"rStaRecBf.nr_bw160      = %d\n"
++					"rStaRecBf.nc_bw160 	  = %d\n"
++					"rStaRecBf.ru_start_idx  = %d\n"
++					"rStaRecBf.ru_end_idx 	  = %d\n"
++					"rStaRecBf.trigger_su 	  = %d\n"
++					"rStaRecBf.trigger_mu 	  = %d\n"
++					"rStaRecBf.ng16_su 	  = %d\n"
++					"rStaRecBf.ng16_mu 	  = %d\n"
++					"rStaRecBf.codebook42_su = %d\n"
++					"rStaRecBf.codebook75_mu = %d\n"
++					"rStaRecBf.he_ltf 	      = %d\n"
++					"rStaRecBf.pp_fd_val 	  = %d\n"
++					"======================================\n",
++					r->smart_ant,
++					r->se_idx,
++					r->bf_timeout,
++					r->bf_dbw,
++					r->bf_ncol,
++					r->bf_nrow,
++					r->nr_lt_bw80,
++					r->nc_lt_bw80,
++					r->ru_start_idx,
++					r->ru_end_idx,
++					r->trigger_su,
++					r->trigger_mu,
++					r->ng16_su,
++					r->ng16_mu,
++					r->codebook42_su,
++					r->codebook75_mu,
++					r->he_ltf,
++					r->pp_fd_val);
++		break;
++	}
++	case UNI_EVENT_BF_FBK_INFO: {
++		struct mt7996_mcu_txbf_fbk_info *info;
++		__le32 total, i;
++
++		info = (struct mt7996_mcu_txbf_fbk_info *)skb->data;
++
++		total = info->u4PFMUWRDoneCnt + info->u4PFMUWRFailCnt;
++		total += info->u4PFMUWRTimeoutFreeCnt + info->u4FbRptPktDropCnt;
++
++		dev_info(dev->mt76.dev, "\n");
++		dev_info(dev->mt76.dev, "\x1b[32m =================================\x1b[m\n");
++		dev_info(dev->mt76.dev, "\x1b[32m PFMUWRDoneCnt              = %u\x1b[m\n",
++			info->u4PFMUWRDoneCnt);
++		dev_info(dev->mt76.dev, "\x1b[32m PFMUWRFailCnt              = %u\x1b[m\n",
++			info->u4PFMUWRFailCnt);
++		dev_info(dev->mt76.dev, "\x1b[32m PFMUWRTimeOutCnt           = %u\x1b[m\n",
++			info->u4PFMUWRTimeOutCnt);
++		dev_info(dev->mt76.dev, "\x1b[32m PFMUWRTimeoutFreeCnt       = %u\x1b[m\n",
++			info->u4PFMUWRTimeoutFreeCnt);
++		dev_info(dev->mt76.dev, "\x1b[32m FbRptPktDropCnt            = %u\x1b[m\n",
++			info->u4FbRptPktDropCnt);
++		dev_info(dev->mt76.dev, "\x1b[32m TotalFbRptPkt              = %u\x1b[m\n", total);
++		dev_info(dev->mt76.dev, "\x1b[32m PollPFMUIntrStatTimeOut    = %u(micro-sec)\x1b[m\n",
++			info->u4PollPFMUIntrStatTimeOut);
++		dev_info(dev->mt76.dev, "\x1b[32m FbRptDeQInterval           = %u(milli-sec)\x1b[m\n",
++			info->u4DeQInterval);
++		dev_info(dev->mt76.dev, "\x1b[32m PktCntInFbRptTimeOutQ      = %u\x1b[m\n",
++			info->u4RptPktTimeOutListNum);
++		dev_info(dev->mt76.dev, "\x1b[32m PktCntInFbRptQ             = %u\x1b[m\n",
++			info->u4RptPktListNum);
++
++		// [ToDo] Check if it is valid entry
++		for (i = 0; ((i < 5) && (i < CFG_BF_STA_REC_NUM)); i++) {
++
++			// [ToDo] AID needs to be refined
++			dev_info(dev->mt76.dev,"\x1b[32m AID%u  RxFbRptCnt           = %u\x1b[m\n"
++				, i, info->au4RxPerStaFbRptCnt[i]);
++		}
++
++		break;
++	}
++	case UNI_EVENT_BF_TXSND_INFO: {
++		struct mt7996_mcu_tx_snd_info *info;
++		struct uni_event_bf_txsnd_sta_info *snd_sta_info;
++		int Idx;
++		int max_wtbl_size = mt7996_wtbl_size(dev);
++
++		info = (struct mt7996_mcu_tx_snd_info *)skb->data;
++		dev_info(dev->mt76.dev, "=================== Global Setting ===================\n");
++
++		dev_info(dev->mt76.dev, "VhtOpt = 0x%02X, HeOpt = 0x%02X, GloOpt = 0x%02X\n",
++			info->vht_opt, info->he_opt, info->glo_opt);
++
++		for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++			dev_info(dev->mt76.dev, "SuSta[%d] = 0x%08X,", Idx,
++				 info->snd_rec_su_sta[Idx]);
++			if ((Idx & 0x03) == 0x03)
++				dev_info(dev->mt76.dev, "\n");
++		}
++
++		if ((Idx & 0x03) != 0x03)
++			dev_info(dev->mt76.dev, "\n");
++
++
++		for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++			dev_info(dev->mt76.dev, "VhtMuSta[%d] = 0x%08X,", Idx, info->snd_rec_vht_mu_sta[Idx]);
++			if ((Idx & 0x03) == 0x03)
++				dev_info(dev->mt76.dev, "\n");
++		}
++
++		if ((Idx & 0x03) != 0x03)
++			dev_info(dev->mt76.dev, "\n");
++
++		for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++			dev_info(dev->mt76.dev, "HeTBSta[%d] = 0x%08X,", Idx, info->snd_rec_he_tb_sta[Idx]);
++			if ((Idx & 0x03) == 0x03)
++				dev_info(dev->mt76.dev, "\n");
++		}
++
++		if ((Idx & 0x03) != 0x03)
++			dev_info(dev->mt76.dev, "\n");
++
++		for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++			dev_info(dev->mt76.dev, "EhtTBSta[%d] = 0x%08X,", Idx, info->snd_rec_eht_tb_sta[Idx]);
++			if ((Idx & 0x03) == 0x03)
++				dev_info(dev->mt76.dev, "\n");
++		}
++
++		if ((Idx & 0x03) != 0x03)
++			dev_info(dev->mt76.dev, "\n");
++
++		for (Idx = 0; Idx < CFG_WIFI_RAM_BAND_NUM; Idx++) {
++			dev_info(dev->mt76.dev, "Band%u:\n", Idx);
++			dev_info(dev->mt76.dev, "	 Wlan Idx For VHT MC Sounding = %u\n", info->wlan_idx_for_mc_snd[Idx]);
++			dev_info(dev->mt76.dev, "	 Wlan Idx For HE TB Sounding = %u\n", info->wlan_idx_for_he_tb_snd[Idx]);
++			dev_info(dev->mt76.dev, "	 Wlan Idx For EHT TB Sounding = %u\n", info->wlan_idx_for_eht_tb_snd[Idx]);
++		}
++
++		dev_info(dev->mt76.dev, "ULLen = %d, ULMcs = %d, ULLDCP = %d\n",
++			info->ul_length, info->mcs, info->ldpc);
++
++		dev_info(dev->mt76.dev, "=================== STA Info ===================\n");
++
++		for (Idx = 1; (Idx < 5 && (Idx < CFG_BF_STA_REC_NUM)); Idx++) {
++			snd_sta_info = &info->snd_sta_info[Idx];
++			dev_info(dev->mt76.dev, "Idx%2u Interval = %d, interval counter = %d, TxCnt = %d, StopReason = 0x%02X\n",
++				Idx,
++				snd_sta_info->snd_intv,
++				snd_sta_info->snd_intv_cnt,
++				snd_sta_info->snd_tx_cnt,
++				snd_sta_info->snd_stop_reason);
++		}
++
++		dev_info(dev->mt76.dev, "=================== STA Info Connected ===================\n");
++		// [ToDo] How to iterate and get AID info of station
++		// Check UniEventBFCtrlTxSndHandle() on Logan
++
++		//hardcode max_wtbl_size as 5
++		max_wtbl_size = 5;
++		for (Idx = 1; ((Idx < max_wtbl_size) && (Idx < CFG_BF_STA_REC_NUM)); Idx++) {
++
++			// [ToDo] We do not show AID info here
++			snd_sta_info = &info->snd_sta_info[Idx];
++			dev_info(dev->mt76.dev, " Interval = %d (%u ms), interval counter = %d (%u ms), TxCnt = %d, StopReason = 0x%02X\n",
++				snd_sta_info->snd_intv,
++				snd_sta_info->snd_intv * 10,
++				snd_sta_info->snd_intv_cnt,
++				snd_sta_info->snd_intv_cnt * 10,
++				snd_sta_info->snd_tx_cnt,
++				snd_sta_info->snd_stop_reason);
++		}
++
++		dev_info(dev->mt76.dev, "======================================\n");
++
++		break;
++	}
++	default:
++		dev_info(dev->mt76.dev, "%s: unknown bf event tag %d\n",
++			 __func__, event->tag);
++	}
++
++}
++
++
++int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val)
++{
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		__le16 value;
++		__le16 rsv;
++	} __packed data = {
++		.tag = cpu_to_le16(action),
++		.len = cpu_to_le16(sizeof(data) - 4),
++		.value = cpu_to_le16(!!val),
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data, sizeof(data),
++				 false);
++}
++
++int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para)
++{
++	char *buf = (char *)para;
++	u8 num_user = 0, recv_arg = 0, max_mcs = 0, usr_mcs[4] = {0};
++	__le16 bw;
++	int i;
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 cmd_version;
++		u8 cmd_revision;
++		__le16 rsv;
++
++		struct uni_muru_mum_set_group_tbl_entry entry;
++	} __packed data = {
++		.tag = cpu_to_le16(action),
++		.len = cpu_to_le16(sizeof(data) - 4),
++	};
++
++#define __RUALLOC_TYPE_CHECK_HE(BW) ((BW == RUALLOC_BW20) || (BW == RUALLOC_BW40) || (BW == RUALLOC_BW80) || (BW == RUALLOC_BW160))
++#define __RUALLOC_TYPE_CHECK_EHT(BW) (__RUALLOC_TYPE_CHECK_HE(BW) || (BW == RUALLOC_BW320))
++	/* [Num of user] - 1~4
++	 * [RUAlloc] - BW320: 395, BW160: 137, BW80: 134, BW40: 130, BW20: 122
++	 * [LTF/GI] - For VHT, short GI: 0, Long GI: 1; 	 *
++	 * For HE/EHT, 4xLTF+3.2us: 0, 4xLTF+0.8us: 1, 2xLTF+0.8us:2
++	 * [Phy/FullBW] - VHT: 0 / HEFullBw: 1 / HEPartialBw: 2 / EHTFullBW: 3, EHTPartialBW: 4
++	 * [DL/UL] DL: 0, UL: 1, DL_UL: 2
++	 * [Wcid User0] - WCID 0
++	 * [MCS of WCID0] - For HE/VHT, 0-11: 1ss MCS0-MCS11, 12-23: 2SS MCS0-MCS11
++	 * For EHT, 0-13: 1ss MCS0-MCS13, 14-27: 2SS MCS0-MCS13
++	 * [WCID 1]
++	 * [MCS of WCID1]
++	 * [WCID 2]
++	 * [MCS of WCID2]
++	 * [WCID 3]
++	 * [MCS of WCID3]
++	 */
++
++	recv_arg = sscanf(buf, "%hhu %hu %hhu %hhu %hhu %hu %hhu %hu %hhu %hu %hhu %hu %hhu",
++			  &num_user, &bw, &data.entry.gi, &data.entry.capa, &data.entry.dl_ul,
++			  &data.entry.wlan_idx0, &usr_mcs[0],
++			  &data.entry.wlan_idx1, &usr_mcs[1],
++			  &data.entry.wlan_idx2, &usr_mcs[2],
++			  &data.entry.wlan_idx3, &usr_mcs[3]);
++
++	if (recv_arg != (5 + (2 * num_user))) {
++		dev_err(dev->mt76.dev, "The number of argument is invalid\n");
++		goto error;
++	}
++
++	if (num_user > 0 && num_user < 5)
++		data.entry.num_user = num_user - 1;
++	else {
++		dev_err(dev->mt76.dev, "The number of user count is invalid\n");
++		goto error;
++	}
++
++	/**
++	 * Older chip shall be set as HE. Refer to getHWSupportByChip() in Logan
++	 * driver to know the value for differnt chips
++	 */
++	data.cmd_version = UNI_CMD_MURU_VER_EHT;
++
++	if (data.cmd_version == UNI_CMD_MURU_VER_EHT)
++		max_mcs = UNI_MAX_MCS_SUPPORT_EHT;
++	else
++		max_mcs = UNI_MAX_MCS_SUPPORT_HE;
++
++
++	// Parameter Check
++	if (data.cmd_version != UNI_CMD_MURU_VER_EHT) {
++		if ((data.entry.capa > MAX_MODBF_HE) || (bw == RUALLOC_BW320))
++			goto error;
++	} else {
++		if ((data.entry.capa <= MAX_MODBF_HE) && (bw == RUALLOC_BW320))
++			goto error;
++	}
++
++	if (data.entry.capa <= MAX_MODBF_HE)
++		max_mcs = UNI_MAX_MCS_SUPPORT_HE;
++
++	if (__RUALLOC_TYPE_CHECK_EHT(bw)) {
++		data.entry.ru_alloc = (u8)(bw & 0xFF);
++		if (bw == RUALLOC_BW320)
++			data.entry.ru_alloc_ext = (u8)(bw >> 8);
++	} else {
++		dev_err(dev->mt76.dev, "RU_ALLOC argument is invalid\n");
++		goto error;
++	}
++
++	if ((data.entry.gi > 2) ||
++	    ((data.entry.gi > 1) && (data.entry.capa == MAX_MODBF_VHT))) {
++		dev_err(dev->mt76.dev, "GI argument is invalid\n");
++		goto error;
++	}
++
++	if (data.entry.dl_ul > 2) {
++		dev_err(dev->mt76.dev, "DL_UL argument is invalid\n");
++		goto error;
++	}
++
++#define __mcs_handler(_n)							\
++	do {									\
++		if (usr_mcs[_n] > max_mcs) {					\
++			usr_mcs[_n] -= (max_mcs + 1);				\
++			data.entry.nss##_n = 1;					\
++			if (usr_mcs[_n] > max_mcs)				\
++				usr_mcs[_n] = max_mcs;				\
++		}								\
++		if ((data.entry.dl_ul & 0x1) == 0)				\
++			data.entry.dl_mcs_user##_n = usr_mcs[_n];		\
++		if ((data.entry.dl_ul & 0x3) > 0)				\
++			data.entry.ul_mcs_user##_n = usr_mcs[_n];		\
++	}									\
++	while (0)
++
++	for (i=0; i<= data.entry.num_user; i++) {
++		switch (i) {
++			case 0:
++				__mcs_handler(0);
++				break;
++			case 1:
++				__mcs_handler(1);
++				break;
++			case 2:
++				__mcs_handler(2);
++				break;
++			case 3:
++				__mcs_handler(3);
++				break;
++			default:
++				break;
++		}
++	}
++#undef __mcs_handler
++
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data,
++				 sizeof(data), false);
++
++error:
++	dev_err(dev->mt76.dev, "Command failed!\n");
++	return -EINVAL;
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index cc2de8f4..519ffe1c 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -106,6 +106,348 @@ enum {
+ 	EDCCA_FCC = 1,
+ 	EDCCA_ETSI = 2,
+ 	EDCCA_JAPAN = 3
++
++struct bf_pfmu_tag {
++	__le16 tag;
++	__le16 len;
++
++	u8 pfmu_id;
++	bool bfer;
++	u8 band_idx;
++	u8 __rsv[5];
++	u8 buf[56];
++} __packed;
++
++struct bf_starec_read {
++	__le16 tag;
++	__le16 len;
++
++	__le16 wlan_idx;
++	u8 __rsv[2];
++} __packed;
++
++struct bf_fbk_rpt_info {
++	__le16 tag;
++	__le16 len;
++
++	__le16 wlan_idx; // Only need for dynamic_pfmu_update 0x4
++	u8 action;
++	u8 band_idx;
++	u8 __rsv[4];
++
++} __packed;
++
++struct bf_txsnd_info {
++	__le16 tag;
++	__le16 len;
++
++	u8 action;
++	u8 read_clr;
++	u8 vht_opt;
++	u8 he_opt;
++	__le16 wlan_idx;
++	u8 glo_opt;
++	u8 snd_intv;
++	u8 snd_stop;
++	u8 max_snd_stas;
++	u8 tx_time;
++	u8 mcs;
++	u8 ldpc;
++	u8 inf;
++	u8 man;
++	u8 ac_queue;
++	u8 sxn_protect;
++	u8 direct_fbk;
++	u8 __rsv[2];
++} __packed;
++
++struct mt7996_mcu_bf_basic_event {
++	struct mt7996_mcu_rxd rxd;
++
++	u8 __rsv1[4];
++
++	__le16 tag;
++	__le16 len;
++};
++
++struct mt7996_mcu_bf_starec_read {
++
++	struct mt7996_mcu_bf_basic_event event;
++
++	__le16 pfmu_id;
++	bool is_su_mu;
++	u8 txbf_cap;
++	u8 sounding_phy;
++	u8 ndpa_rate;
++	u8 ndp_rate;
++	u8 rpt_poll_rate;
++	u8 tx_mode;
++	u8 nc;
++	u8 nr;
++	u8 bw;
++	u8 total_mem_require;
++	u8 mem_require_20m;
++	u8 mem_row0;
++	u8 mem_col0:6;
++	u8 mem_row0_msb:2;
++	u8 mem_row1;
++	u8 mem_col1:6;
++	u8 mem_row1_msb:2;
++	u8 mem_row2;
++	u8 mem_col2:6;
++	u8 mem_row2_msb:2;
++	u8 mem_row3;
++	u8 mem_col3:6;
++	u8 mem_row3_msb:2;
++
++	__le16 smart_ant;
++	u8 se_idx;
++	u8 auto_sounding_ctrl;
++
++	u8 bf_timeout;
++	u8 bf_dbw;
++	u8 bf_ncol;
++	u8 bf_nrow;
++
++	u8 nr_lt_bw80;
++	u8 nc_lt_bw80;
++	u8 ru_start_idx;
++	u8 ru_end_idx;
++
++	bool trigger_su;
++	bool trigger_mu;
++
++	bool ng16_su;
++	bool ng16_mu;
++
++	bool codebook42_su;
++	bool codebook75_mu;
++
++	u8 he_ltf;
++	u8 pp_fd_val;
++};
++
++#define TXBF_PFMU_ID_NUM_MAX 48
++
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND0 TXBF_PFMU_ID_NUM_MAX
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND1 TXBF_PFMU_ID_NUM_MAX
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND2 TXBF_PFMU_ID_NUM_MAX
++
++/* CFG_BF_STA_REC shall be varied based on BAND Num */
++#define CFG_BF_STA_REC_NUM (TXBF_PFMU_ID_NUM_MAX_TBTC_BAND0 + TXBF_PFMU_ID_NUM_MAX_TBTC_BAND1 + TXBF_PFMU_ID_NUM_MAX_TBTC_BAND2)
++
++#define BF_SND_CTRL_STA_DWORD_CNT   ((CFG_BF_STA_REC_NUM + 0x1F) >> 5)
++
++#ifndef ALIGN_4
++	#define ALIGN_4(_value)             (((_value) + 3) & ~3u)
++#endif /* ALIGN_4 */
++
++#define CFG_WIFI_RAM_BAND_NUM 3
++
++struct uni_event_bf_txsnd_sta_info {
++	u8 snd_intv;       /* Sounding interval upper bound, unit:15ms */
++	u8 snd_intv_cnt;   /* Sounding interval counter */
++	u8 snd_tx_cnt;     /* Tx sounding count for debug */
++	u8 snd_stop_reason;  /* Bitwise reason to put in Stop Queue */
++};
++
++struct mt7996_mcu_tx_snd_info {
++
++	struct mt7996_mcu_bf_basic_event event;
++
++	u8 vht_opt;
++	u8 he_opt;
++	u8 glo_opt;
++	u8 __rsv;
++	__le32 snd_rec_su_sta[BF_SND_CTRL_STA_DWORD_CNT];
++	__le32 snd_rec_vht_mu_sta[BF_SND_CTRL_STA_DWORD_CNT];
++	__le32 snd_rec_he_tb_sta[BF_SND_CTRL_STA_DWORD_CNT];
++	__le32 snd_rec_eht_tb_sta[BF_SND_CTRL_STA_DWORD_CNT];
++	__le16 wlan_idx_for_mc_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++	__le16 wlan_idx_for_he_tb_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++	__le16 wlan_idx_for_eht_tb_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++	__le16 ul_length;
++	u8 mcs;
++	u8 ldpc;
++	struct uni_event_bf_txsnd_sta_info snd_sta_info[CFG_BF_STA_REC_NUM];
++};
++
++struct mt7996_mcu_txbf_fbk_info {
++
++	struct mt7996_mcu_bf_basic_event event;
++
++	__le32 u4DeQInterval;     /* By ms */
++	__le32 u4PollPFMUIntrStatTimeOut; /* micro-sec */
++	__le32 u4RptPktTimeOutListNum;
++	__le32 u4RptPktListNum;
++	__le32 u4PFMUWRTimeOutCnt;
++	__le32 u4PFMUWRFailCnt;
++	__le32 u4PFMUWRDoneCnt;
++	__le32 u4PFMUWRTimeoutFreeCnt;
++	__le32 u4FbRptPktDropCnt;
++	__le32 au4RxPerStaFbRptCnt[CFG_BF_STA_REC_NUM];
++};
++
++struct pfmu_ru_field {
++	__le32 ru_start_id:7;
++	__le32 _rsv1:1;
++	__le32 ru_end_id:7;
++	__le32 _rsv2:1;
++} __packed;
++
++struct pfmu_partial_bw_info {
++	__le32 partial_bw_info:9;
++	__le32 _rsv1:7;
++} __packed;
++
++struct mt7996_pfmu_tag1 {
++	__le32 pfmu_idx:10;
++	__le32 ebf:1;
++	__le32 data_bw:3;
++	__le32 lm:3;
++	__le32 is_mu:1;
++	__le32 nr:3;
++	__le32 nc:3;
++	__le32 codebook:2;
++	__le32 ngroup:2;
++	__le32 invalid_prof:1;
++	__le32 _rsv:3;
++
++	__le32 col_id1:7, row_id1:9;
++	__le32 col_id2:7, row_id2:9;
++	__le32 col_id3:7, row_id3:9;
++	__le32 col_id4:7, row_id4:9;
++
++	union {
++		struct pfmu_ru_field field;
++		struct pfmu_partial_bw_info bw_info;
++	};
++	__le32 mob_cal_en:1;
++	__le32 _rsv2:3;
++	__le32 mob_ru_alloc:9;	/* EHT profile uses full 9 bit */
++	__le32 _rsv3:3;
++
++	__le32 snr_sts0:8, snr_sts1:8, snr_sts2:8, snr_sts3:8;
++	__le32 snr_sts4:8, snr_sts5:8, snr_sts6:8, snr_sts7:8;
++
++	__le32 _rsv4;
++} __packed;
++
++struct mt7996_pfmu_tag2 {
++	__le32 smart_ant:24;
++	__le32 se_idx:5;
++	__le32 _rsv:3;
++
++	__le32 _rsv1:16;
++	__le32 ibf_timeout:8;
++	__le32 _rsv2:8;
++
++	__le32 ibf_data_bw:3;
++	__le32 ibf_nc:3;
++	__le32 ibf_nr:3;
++	__le32 ibf_ru:9;
++	__le32 _rsv3:14;
++
++	__le32 mob_delta_t:8;
++	__le32 mob_lq_result:7;
++	__le32 _rsv5:1;
++	__le32 _rsv6:16;
++
++	__le32 _rsv7;
++} __packed;
++
++struct mt7996_pfmu_tag_event {
++	struct mt7996_mcu_bf_basic_event event;
++
++	u8 bfer;
++	u8 __rsv[3];
++
++	struct mt7996_pfmu_tag1 t1;
++	struct mt7996_pfmu_tag2 t2;
++};
++
++enum {
++	UNI_EVENT_BF_PFMU_TAG = 0x5,
++	UNI_EVENT_BF_PFMU_DATA = 0x7,
++	UNI_EVENT_BF_STAREC = 0xB,
++	UNI_EVENT_BF_CAL_PHASE = 0xC,
++	UNI_EVENT_BF_FBK_INFO = 0x17,
++	UNI_EVENT_BF_TXSND_INFO = 0x18,
++	UNI_EVENT_BF_PLY_INFO = 0x19,
++	UNI_EVENT_BF_METRIC_INFO = 0x1A,
++	UNI_EVENT_BF_TXCMD_CFG_INFO = 0x1B,
++	UNI_EVENT_BF_SND_CNT_INFO = 0x1D,
++	UNI_EVENT_BF_MAX_NUM
++};
++
++enum {
++	UNI_CMD_MURU_FIXED_RATE_CTRL = 0x11,
++	UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++};
++
++struct uni_muru_mum_set_group_tbl_entry {
++	__le16 wlan_idx0;
++	__le16 wlan_idx1;
++	__le16 wlan_idx2;
++	__le16 wlan_idx3;
++
++	u8 dl_mcs_user0:4;
++	u8 dl_mcs_user1:4;
++	u8 dl_mcs_user2:4;
++	u8 dl_mcs_user3:4;
++	u8 ul_mcs_user0:4;
++	u8 ul_mcs_user1:4;
++	u8 ul_mcs_user2:4;
++	u8 ul_mcs_user3:4;
++
++	u8 num_user:2;
++	u8 rsv:6;
++	u8 nss0:2;
++	u8 nss1:2;
++	u8 nss2:2;
++	u8 nss3:2;
++	u8 ru_alloc;
++	u8 ru_alloc_ext;
++
++	u8 capa;
++	u8 gi;
++	u8 dl_ul;
++	u8 _rsv2;
++};
++
++enum UNI_CMD_MURU_VER_T {
++	UNI_CMD_MURU_VER_LEG = 0,
++	UNI_CMD_MURU_VER_HE,
++	UNI_CMD_MURU_VER_EHT,
++	UNI_CMD_MURU_VER_MAX
++};
++
++#define UNI_MAX_MCS_SUPPORT_HE 11
++#define UNI_MAX_MCS_SUPPORT_EHT 13
++
++enum {
++	RUALLOC_BW20 = 122,
++	RUALLOC_BW40 = 130,
++	RUALLOC_BW80 = 134,
++	RUALLOC_BW160 = 137,
++	RUALLOC_BW320 = 395,
++};
++
++enum {
++	MAX_MODBF_VHT = 0,
++	MAX_MODBF_HE = 2,
++	MAX_MODBF_EHT = 4,
++};
++
++enum {
++	BF_SND_READ_INFO = 0,
++	BF_SND_CFG_OPT,
++	BF_SND_CFG_INTV,
++	BF_SND_STA_STOP,
++	BF_SND_CFG_MAX_STA,
++	BF_SND_CFG_BFRP,
++	BF_SND_CFG_INF,
++	BF_SND_CFG_TXOP_SND
+ };
+ 
+ enum {
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch
deleted file mode 100644
index 3af30bf..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1030-wifi-mt76-mt7996-add-wtbl_info-support-for-kite.patch
+++ /dev/null
@@ -1,198 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1031-mtk-wifi-mt76-mt7996-add-build-the-following-MURU-mc.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1031-mtk-wifi-mt76-mt7996-add-build-the-following-MURU-mc.patch
new file mode 100644
index 0000000..bd1a654
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1031-mtk-wifi-mt76-mt7996-add-build-the-following-MURU-mc.patch
@@ -0,0 +1,189 @@
+From 16c194f2e8eb3bbe932ef58569eefa1dfb806264 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Tue, 13 Jun 2023 14:49:02 +0800
+Subject: [PATCH 1031/1041] mtk: wifi: mt76: mt7996: add build the following
+ MURU mcu command tlvs
+
+It includes the following tlvs:
+1. MURU tlv id 0x10, 0x33, 0xC8, 0xC9, 0xCA, 0xCC, 0xCD
+2. BF tlv id 0x1c
+
+---
+ mt7996/mcu.h         |  1 +
+ mt7996/mt7996.h      |  3 ++
+ mt7996/mtk_debugfs.c | 12 +++++++
+ mt7996/mtk_mcu.c     | 78 ++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h     | 14 ++++++++
+ 5 files changed, 108 insertions(+)
+
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 347893c8..527c9c79 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -776,6 +776,7 @@ enum {
+ 	BF_MOD_EN_CTRL = 20,
+ 	BF_FBRPT_DBG_INFO_READ = 23,
+ 	BF_TXSND_INFO = 24,
++	BF_CFG_PHY = 28,
+ };
+ 
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index a321e8e8..9df6b25c 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -814,6 +814,9 @@ void mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val);
+ int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para);
+ int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para);
++int mt7996_mcu_set_muru_cmd(struct mt7996_dev *dev, u16 action, int val);
++int mt7996_mcu_muru_set_prot_frame_thr(struct mt7996_dev *dev, u32 val);
++int mt7996_mcu_set_bypass_smthint(struct mt7996_phy *phy, u8 val);
+ #endif
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 938da645..1530ad79 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2909,6 +2909,16 @@ static const struct file_operations fops_muru_fixed_group_rate = {
+ 	.llseek = default_llseek,
+ };
+ 
++static int mt7996_muru_prot_thr_set(void *data, u64 val)
++{
++	struct mt7996_phy *phy = data;
++
++	return mt7996_mcu_muru_set_prot_frame_thr(phy->dev, (u32)val);
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_prot_thr, NULL,
++			 mt7996_muru_prot_thr_set, "%lld\n");
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -3003,6 +3013,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 	debugfs_create_file("bf_fbk_rpt", 0600, dir, phy, &fops_bf_fbk_rpt);
+ 	debugfs_create_file("pfmu_tag_read", 0600, dir, phy, &fops_bf_pfmu_tag_read);
+ 
++	debugfs_create_file("muru_prot_thr", 0200, dir, phy, &fops_muru_prot_thr);
++
+ 	return 0;
+ }
+ 
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index 67419cd9..b7d86384 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -906,4 +906,82 @@ error:
+ 	return -EINVAL;
+ }
+ 
++/**
++ * This function can be used to build the following commands
++ * MURU_SUTX_CTRL (0x10)
++ * SET_FORCE_MU (0x33)
++ * SET_MUDL_ACK_POLICY (0xC8)
++ * SET_TRIG_TYPE (0xC9)
++ * SET_20M_DYN_ALGO (0xCA)
++ * SET_CERT_MU_EDCA_OVERRIDE (0xCD)
++ */
++int mt7996_mcu_set_muru_cmd(struct mt7996_dev *dev, u16 action, int val)
++{
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 config;
++		u8 rsv[3];
++	} __packed data = {
++		.tag = cpu_to_le16(action),
++		.len = cpu_to_le16(sizeof(data) - 4),
++		.config = (u8) val,
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data, sizeof(data),
++				 false);
++}
++
++int mt7996_mcu_muru_set_prot_frame_thr(struct mt7996_dev *dev, u32 val)
++{
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		__le32 prot_frame_thr;
++	} __packed data = {
++		.tag = cpu_to_le16(UNI_CMD_MURU_PROT_FRAME_THR),
++		.len = cpu_to_le16(sizeof(data) - 4),
++		.prot_frame_thr = cpu_to_le32(val),
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data, sizeof(data),
++				 false);
++}
++
++int mt7996_mcu_set_bypass_smthint(struct mt7996_phy *phy, u8 val)
++{
++#define BF_PHY_SMTH_INT_BYPASS 0
++#define BYPASS_VAL 1
++	struct mt7996_dev *dev = phy->dev;
++	struct {
++		u8 _rsv[4];
++
++		u16 tag;
++		u16 len;
++
++		u8 action;
++		u8 band_idx;
++		u8 smthintbypass;
++		u8 __rsv2[5];
++	} __packed data = {
++		.tag = cpu_to_le16(BF_CFG_PHY),
++		.len = cpu_to_le16(sizeof(data) - 4),
++		.action = BF_PHY_SMTH_INT_BYPASS,
++		.band_idx = phy->mt76->band_idx,
++		.smthintbypass = val,
++	};
++
++	if (val != BYPASS_VAL)
++		return -EINVAL;
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &data, sizeof(data),
++				 true);
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index 519ffe1c..eedc3589 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -106,6 +106,20 @@ enum {
+ 	EDCCA_FCC = 1,
+ 	EDCCA_ETSI = 2,
+ 	EDCCA_JAPAN = 3
++};
++
++enum {
++	UNI_CMD_MURU_SUTX_CTRL = 0x10,
++	UNI_CMD_MURU_FIXED_RATE_CTRL,
++	UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++	UNI_CMD_MURU_SET_FORCE_MU = 0x33,
++	UNI_CMD_MURU_MUNUAL_CONFIG = 0x64,
++	UNI_CMD_MURU_SET_MUDL_ACK_POLICY = 0xC9,
++	UNI_CMD_MURU_SET_TRIG_TYPE,
++	UNI_CMD_MURU_SET_20M_DYN_ALGO,
++	UNI_CMD_MURU_PROT_FRAME_THR = 0xCC,
++	UNI_CMD_MURU_SET_CERT_MU_EDCA_OVERRIDE,
++};
+ 
+ struct bf_pfmu_tag {
+ 	__le16 tag;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1032-mtk-wifi-mt76-mt7996-add-cert-patch.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1032-mtk-wifi-mt76-mt7996-add-cert-patch.patch
new file mode 100644
index 0000000..ca22864
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1032-mtk-wifi-mt76-mt7996-add-cert-patch.patch
@@ -0,0 +1,1094 @@
+From 0a36115fd164506e65bcbef9444f6664ba833c04 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Mon, 14 Aug 2023 13:36:58 +0800
+Subject: [PATCH 1032/1041] mtk: wifi: mt76: mt7996: add cert patch
+
+This patch includes TGac and TGax
+
+Commit histroy:
+
+Add vendor cmd set ap wireless rts_sigta support
+
+Signed-off-by: ye he <ye.he@mediatek.com>
+---
+ mt7996/mac.c     |   9 ++
+ mt7996/main.c    |  31 ++++++-
+ mt7996/mcu.c     |  40 +++++++++
+ mt7996/mcu.h     |   6 ++
+ mt7996/mt7996.h  |  13 +++
+ mt7996/mtk_mcu.c | 206 ++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h | 184 +++++++++++++++++++++++++++++++++++--
+ mt7996/vendor.c  | 230 ++++++++++++++++++++++++++++++++++++++++++++++-
+ mt7996/vendor.h  |  67 ++++++++++++++
+ 9 files changed, 779 insertions(+), 7 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 73c66e57..27e5fb71 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -10,6 +10,7 @@
+ #include "../dma.h"
+ #include "mac.h"
+ #include "mcu.h"
++#include "vendor.h"
+ 
+ #define to_rssi(field, rcpi)	((FIELD_GET(field, rcpi) - 220) / 2)
+ 
+@@ -2272,6 +2273,14 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
+ 	}
+ }
+ 
++void mt7996_set_wireless_amsdu(struct ieee80211_hw *hw, u8 en)
++{
++	if (en)
++		ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
++	else
++		ieee80211_hw_clear(hw, SUPPORTS_AMSDU_IN_AMPDU);
++}
++
+ void mt7996_mac_sta_rc_work(struct work_struct *work)
+ {
+ 	struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 36894828..5a5b549a 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -588,6 +588,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		       bool beacon, bool mcast)
+ {
+ 	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
++	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ 	struct mt76_phy *mphy = hw->priv;
+ 	u16 rate;
+ 	u8 i, idx;
+@@ -597,6 +598,9 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 	if (beacon) {
+ 		struct mt7996_phy *phy = mphy->priv;
+ 
++		if (dev->cert_mode && phy->mt76->band_idx == MT_BAND2)
++			rate = 0x0200;
++
+ 		/* odd index for driver, even index for firmware */
+ 		idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
+ 		if (phy->beacon_rate != rate)
+@@ -726,6 +730,10 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ 	u8 band_idx = mvif->phy->mt76->band_idx;
+ 	int ret, idx;
+ 
++#ifdef CONFIG_MTK_VENDOR
++	struct mt7996_phy *phy = &dev->phy;
++#endif
++
+ 	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
+ 	if (idx < 0)
+ 		return -ENOSPC;
+@@ -751,7 +759,28 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ 	if (ret)
+ 		return ret;
+ 
+-	return mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
++	ret = mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
++	if (ret)
++		return ret;
++
++#ifdef CONFIG_MTK_VENDOR
++	switch (band_idx) {
++	case MT_BAND1:
++		phy = mt7996_phy2(dev);
++		break;
++	case MT_BAND2:
++		phy = mt7996_phy3(dev);
++		break;
++	case MT_BAND0:
++	default:
++		break;
++	}
++
++	if (phy && phy->muru_onoff & MUMIMO_DL_CERT)
++		mt7996_mcu_set_mimo(phy);
++#endif
++
++	return 0;
+ }
+ 
+ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index d3dab186..7f235f91 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1359,6 +1359,10 @@ mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ {
+ 	struct sta_rec_vht *vht;
+ 	struct tlv *tlv;
++#ifdef CONFIG_MTK_VENDOR
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++	struct mt7996_phy *phy = (struct mt7996_phy *)msta->vif->phy;
++#endif
+ 
+ 	/* For 6G band, this tlv is necessary to let hw work normally */
+ 	if (!sta->deflink.he_6ghz_capa.capa && !sta->deflink.vht_cap.vht_supported)
+@@ -1370,6 +1374,9 @@ mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ 	vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);
+ 	vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
+ 	vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
++#ifdef CONFIG_MTK_VENDOR
++	vht->rts_bw_sig = phy->rts_bw_sig;
++#endif
+ }
+ 
+ static void
+@@ -4445,6 +4452,27 @@ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
+ 				 &req, sizeof(req), true);
+ }
+ 
++int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable)
++{
++	struct {
++		u8 band_idx;
++		u8 _rsv[3];
++
++		__le16 tag;
++		__le16 len;
++		bool enable;
++		u8 _rsv2[3];
++	} __packed req = {
++		.band_idx = phy->mt76->band_idx,
++		.tag = cpu_to_le16(option),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.enable = enable,
++	};
++
++	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
++				 &req, sizeof(req), true);
++}
++
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable)
+ {
+ 	struct {
+@@ -4959,6 +4987,18 @@ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+ 	val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
+ 
+ 	switch (mode) {
++	case RATE_PARAM_FIXED_OFDMA:
++		if (val == 3)
++			phy->muru_onoff = OFDMA_DL;
++		else
++			phy->muru_onoff = val;
++		break;
++	case RATE_PARAM_FIXED_MIMO:
++		if (val == 0)
++			phy->muru_onoff = MUMIMO_DL_CERT | MUMIMO_DL;
++		else
++			phy->muru_onoff = MUMIMO_UL;
++		break;
+ 	case RATE_PARAM_AUTO_MU:
+ 		if (val < 0 || val > 15) {
+ 			printk("Wrong value! The value is between 0-15.\n");
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 527c9c79..af078edd 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -755,6 +755,8 @@ enum {
+ 	RATE_PARAM_FIXED_GI = 11,
+ 	RATE_PARAM_AUTO = 20,
+ #ifdef CONFIG_MTK_VENDOR
++	RATE_PARAM_FIXED_MIMO = 30,
++	RATE_PARAM_FIXED_OFDMA = 31,
+ 	RATE_PARAM_AUTO_MU = 32,
+ #endif
+ };
+@@ -767,6 +769,7 @@ enum {
+ #define OFDMA_UL                       BIT(1)
+ #define MUMIMO_DL                      BIT(2)
+ #define MUMIMO_UL                      BIT(3)
++#define MUMIMO_DL_CERT                 BIT(4)
+ 
+ enum {
+ 	BF_SOUNDING_ON = 1,
+@@ -853,11 +856,14 @@ enum {
+ 	UNI_BAND_CONFIG_EDCCA_ENABLE = 0x05,
+ 	UNI_BAND_CONFIG_EDCCA_THRESHOLD = 0x06,
+ 	UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
++	UNI_BAND_CONFIG_RTS_SIGTA_EN = 0x09,
++	UNI_BAND_CONFIG_DIS_SECCH_CCA_DET = 0x0a,
+ };
+ 
+ enum {
+ 	UNI_WSYS_CONFIG_FW_LOG_CTRL,
+ 	UNI_WSYS_CONFIG_FW_DBG_CTRL,
++	UNI_CMD_CERT_CFG = 6,
+ };
+ 
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 9df6b25c..e1a191ec 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -348,6 +348,7 @@ struct mt7996_phy {
+ 	} test;
+ #endif
+ #ifdef CONFIG_MTK_VENDOR
++	u8 rts_bw_sig;
+ 	spinlock_t amnt_lock;
+ 	struct mt7996_air_monitor_ctrl amnt_ctrl;
+ #endif
+@@ -475,6 +476,9 @@ struct mt7996_dev {
+ 	} dbg;
+ 	const struct mt7996_dbg_reg_desc *dbg_reg;
+ #endif
++#ifdef CONFIG_MTK_VENDOR
++	bool cert_mode;
++#endif
+ };
+ 
+ enum {
+@@ -672,6 +676,7 @@ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ 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);
++int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable);
+ 
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+@@ -790,6 +795,10 @@ void mt7996_vendor_register(struct mt7996_phy *phy);
+ void mt7996_vendor_amnt_fill_rx(struct mt7996_phy *phy, struct sk_buff *skb);
+ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
+ 				  struct ieee80211_sta *sta);
++void mt7996_set_wireless_amsdu(struct ieee80211_hw *hw, u8 en);
++void mt7996_mcu_set_mimo(struct mt7996_phy *phy);
++int mt7996_set_muru_cfg(struct mt7996_phy *phy, u8 action, u8 val);
++int mt7996_mcu_set_muru_cfg(struct mt7996_phy *phy, void *data);
+ #endif
+ 
+ int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
+@@ -817,6 +826,10 @@ int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para);
+ int mt7996_mcu_set_muru_cmd(struct mt7996_dev *dev, u16 action, int val);
+ int mt7996_mcu_muru_set_prot_frame_thr(struct mt7996_dev *dev, u32 val);
+ int mt7996_mcu_set_bypass_smthint(struct mt7996_phy *phy, u8 val);
++int mt7996_mcu_set_rfeature_trig_type(struct mt7996_phy *phy, u8 enable, u8 trig_type);
++void mt7996_mcu_set_ppdu_tx_type(struct mt7996_phy *phy, u8 ppdu_type);
++void mt7996_mcu_set_nusers_ofdma(struct mt7996_phy *phy, u8 type, u8 ofdma_user_cnt);
++void mt7996_mcu_set_cert(struct mt7996_phy *phy, u8 type);
+ #endif
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index b7d86384..3b8fbe42 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -984,4 +985,209 @@ int mt7996_mcu_set_bypass_smthint(struct mt7996_phy *phy, u8 val)
+ 				 true);
+ }
+ 
++int mt7996_mcu_set_bsrp_ctrl(struct mt7996_phy *phy, u16 interval,
++			     u16 ru_alloc, u32 trig_type, u8 trig_flow, u8 ext_cmd)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		__le16 interval;
++		__le16 ru_alloc;
++		__le32 trigger_type;
++		u8 trigger_flow;
++		u8 ext_cmd_bsrp;
++		u8 band_bitmap;
++		u8 _rsv2;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_MURU_BSRP_CTRL),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.interval = cpu_to_le16(interval),
++		.ru_alloc = cpu_to_le16(ru_alloc),
++		.trigger_type = cpu_to_le32(trig_type),
++		.trigger_flow = trig_flow,
++		.ext_cmd_bsrp = ext_cmd,
++		.band_bitmap = BIT(phy->mt76->band_idx),
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
++				 sizeof(req), false);
++}
++
++int mt7996_mcu_set_rfeature_trig_type(struct mt7996_phy *phy, u8 enable, u8 trig_type)
++{
++	struct mt7996_dev *dev = phy->dev;
++	int ret = 0;
++	char buf[] = "01:00:00:1B";
++
++	if (enable) {
++		ret = mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_TRIG_TYPE, trig_type);
++		if (ret)
++			return ret;
++	}
++
++	switch (trig_type) {
++	case CAPI_BASIC:
++		return mt7996_mcu_set_bsrp_ctrl(phy, 5, 67, 0, 0, enable);
++	case CAPI_BRP:
++		return mt7996_mcu_set_txbf_snd_info(phy, buf);
++	case CAPI_MU_BAR:
++		return mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_MUDL_ACK_POLICY,
++					       MU_DL_ACK_POLICY_MU_BAR);
++	case CAPI_BSRP:
++		return mt7996_mcu_set_bsrp_ctrl(phy, 5, 67, 4, 0, enable);
++	default:
++		return 0;
++	}
++}
++
++int mt7996_mcu_set_muru_cfg(struct mt7996_phy *phy, void *data)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_muru *muru;
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 version;
++		u8 revision;
++		u8 _rsv2[2];
++
++		struct mt7996_muru muru;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_MURU_MUNUAL_CONFIG),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.version = UNI_CMD_MURU_VER_EHT,
++	};
++
++	muru = (struct mt7996_muru *) data;
++	memcpy(&req.muru, muru, sizeof(struct mt7996_muru));
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
++				 sizeof(req), false);
++}
++
++int mt7996_set_muru_cfg(struct mt7996_phy *phy, u8 action, u8 val)
++{
++	struct mt7996_muru *muru;
++	struct mt7996_muru_dl *dl;
++	struct mt7996_muru_ul *ul;
++	struct mt7996_muru_comm *comm;
++	int ret = 0;
++
++	muru = kzalloc(sizeof(struct mt7996_muru), GFP_KERNEL);
++	dl = &muru->dl;
++	ul = &muru->ul;
++	comm = &muru->comm;
++
++	switch (action) {
++	case MU_CTRL_DL_USER_CNT:
++		dl->user_num = val;
++		comm->ppdu_format = MURU_PPDU_HE_MU;
++		comm->sch_type = MURU_OFDMA_SCH_TYPE_DL;
++		muru->cfg_comm = cpu_to_le32(MURU_COMM_SET);
++		muru->cfg_dl = cpu_to_le32(MURU_FIXED_DL_TOTAL_USER_CNT);
++		ret = mt7996_mcu_set_muru_cfg(phy, muru);
++		break;
++	case MU_CTRL_UL_USER_CNT:
++		ul->user_num = val;
++		comm->ppdu_format = MURU_PPDU_HE_TRIG;
++		comm->sch_type = MURU_OFDMA_SCH_TYPE_UL;
++		muru->cfg_comm = cpu_to_le32(MURU_COMM_SET);
++		muru->cfg_ul = cpu_to_le32(MURU_FIXED_UL_TOTAL_USER_CNT);
++		ret = mt7996_mcu_set_muru_cfg(phy, muru);
++		break;
++	default:
++		break;
++	}
++
++	kfree(muru);
++	return ret;
++}
++
++void mt7996_mcu_set_ppdu_tx_type(struct mt7996_phy *phy, u8 ppdu_type)
++{
++	struct mt7996_dev *dev = phy->dev;
++	int enable_su;
++
++	switch (ppdu_type) {
++	case CAPI_SU:
++		enable_su = 1;
++		mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SUTX_CTRL, enable_su);
++		mt7996_set_muru_cfg(phy, MU_CTRL_DL_USER_CNT, 0);
++		break;
++	case CAPI_MU:
++		enable_su = 0;
++		mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SUTX_CTRL, enable_su);
++		break;
++	default:
++		break;
++	}
++}
++
++void mt7996_mcu_set_nusers_ofdma(struct mt7996_phy *phy, u8 type, u8 user_cnt)
++{
++	struct mt7996_dev *dev = phy->dev;
++	int enable_su = 0;
++
++	mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SUTX_CTRL, enable_su);
++	mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_MUDL_ACK_POLICY, MU_DL_ACK_POLICY_SU_BAR);
++	mt7996_mcu_muru_set_prot_frame_thr(dev, 9999);
++
++	mt7996_set_muru_cfg(phy, type, user_cnt);
++}
++
++void mt7996_mcu_set_mimo(struct mt7996_phy *phy)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
++	int disable_ra = 1;
++	char buf[] = "2 134 0 1 0 1 2 2 2";
++	int force_mu = 1;
++
++	switch (chandef->width) {
++	case NL80211_CHAN_WIDTH_20_NOHT:
++	case NL80211_CHAN_WIDTH_20:
++		strscpy(buf, "2 122 0 1 0 1 2 2 2", sizeof(buf));
++		break;
++	case NL80211_CHAN_WIDTH_80:
++		break;
++	case NL80211_CHAN_WIDTH_160:
++		strscpy(buf, "2 137 0 1 0 1 2 2 2", sizeof(buf));
++		break;
++	default:
++		break;
++	}
++
++	mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_MUDL_ACK_POLICY, MU_DL_ACK_POLICY_SU_BAR);
++	mt7996_mcu_set_muru_fixed_rate_enable(dev, UNI_CMD_MURU_FIXED_RATE_CTRL, disable_ra);
++	mt7996_mcu_set_muru_fixed_rate_parameter(dev, UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL, buf);
++	mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_FORCE_MU, force_mu);
++}
++
++void mt7996_mcu_set_cert(struct mt7996_phy *phy, u8 type)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 action;
++		u8 _rsv2[3];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_CERT_CFG),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.action = type, /* 1: CAPI Enable */
++	};
++
++	mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(WSYS_CONFIG), &req,
++			  sizeof(req), false);
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index eedc3589..44cb0327 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -109,14 +109,15 @@ enum {
+ };
+ 
+ enum {
++	UNI_CMD_MURU_BSRP_CTRL = 0x01,
+ 	UNI_CMD_MURU_SUTX_CTRL = 0x10,
+-	UNI_CMD_MURU_FIXED_RATE_CTRL,
+-	UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++	UNI_CMD_MURU_FIXED_RATE_CTRL = 0x11,
++	UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL = 0x12,
+ 	UNI_CMD_MURU_SET_FORCE_MU = 0x33,
+ 	UNI_CMD_MURU_MUNUAL_CONFIG = 0x64,
+-	UNI_CMD_MURU_SET_MUDL_ACK_POLICY = 0xC9,
+-	UNI_CMD_MURU_SET_TRIG_TYPE,
+-	UNI_CMD_MURU_SET_20M_DYN_ALGO,
++	UNI_CMD_MURU_SET_MUDL_ACK_POLICY = 0xC8,
++	UNI_CMD_MURU_SET_TRIG_TYPE = 0xC9,
++	UNI_CMD_MURU_SET_20M_DYN_ALGO = 0xCA,
+ 	UNI_CMD_MURU_PROT_FRAME_THR = 0xCC,
+ 	UNI_CMD_MURU_SET_CERT_MU_EDCA_OVERRIDE,
+ };
+@@ -520,6 +521,179 @@ struct mt7996_mcu_sr_hw_ind_event {
+ 	__le32 sr_ampdu_mpdu_cnt;
+ 	__le32 sr_ampdu_mpdu_acked_cnt;
+ };
++
++struct mt7996_muru_comm {
++	u8 pda_pol;
++	u8 band;
++	u8 spe_idx;
++	u8 proc_type;
++
++	__le16 mlo_ctrl;
++	u8 sch_type;
++	u8 ppdu_format;
++	u8 ac;
++	u8 _rsv[3];
++};
++
++struct mt7996_muru_dl {
++	u8 user_num;
++	u8 tx_mode;
++	u8 bw;
++	u8 gi;
++
++	u8 ltf;
++	u8 mcs;
++	u8 dcm;
++	u8 cmprs;
++
++	__le16 ru[16];
++
++	u8 c26[2];
++	u8 ack_policy;
++	u8 tx_power;
++
++	__le16 mu_ppdu_duration;
++	u8 agc_disp_order;
++	u8 _rsv1;
++
++	u8 agc_disp_pol;
++	u8 agc_disp_ratio;
++	__le16 agc_disp_linkMFG;
++
++	__le16 prmbl_punc_bmp;
++	u8 _rsv2[2];
++
++	struct {
++		__le16 wlan_idx;
++		u8 ru_alloc_seg;
++		u8 ru_idx;
++		u8 ldpc;
++		u8 nss;
++		u8 mcs;
++		u8 mu_group_idx;
++		u8 vht_groud_id;
++		u8 vht_up;
++		u8 he_start_stream;
++		u8 he_mu_spatial;
++		__le16 tx_power_alpha;
++		u8 ack_policy;
++		u8 ru_allo_ps160;
++	} usr[16];
++};
++
++struct mt7996_muru_ul {
++	u8 user_num;
++	u8 tx_mode;
++
++	u8 ba_type;
++	u8 _rsv;
++
++	u8 bw;
++	u8 gi_ltf;
++	__le16 ul_len;
++
++	__le16 trig_cnt;
++	u8 pad;
++	u8 trig_type;
++
++	__le16 trig_intv;
++	u8 trig_ta[ETH_ALEN];
++	__le16 ul_ru[16];
++
++	u8 c26[2];
++	__le16 agc_disp_linkMFG;
++
++	u8 agc_disp_mu_len;
++	u8 agc_disp_pol;
++	u8 agc_disp_ratio;
++	u8 agc_disp_pu_idx;
++
++	struct {
++		__le16 wlan_idx;
++		u8 ru_alloc_seg;
++		u8 ru_idx;
++		u8 ldpc;
++		u8 nss;
++		u8 mcs;
++		u8 target_rssi;
++		__le32 trig_pkt_size;
++		u8 ru_allo_ps160;
++		u8 _rsv2[3];
++	} usr[16];
++};
++
++struct mt7996_muru_dbg {
++	/* HE TB RX Debug */
++	__le32 rx_hetb_nonsf_en_bitmap;
++	__le32 rx_hetb_cfg[2];
++};
++
++struct mt7996_muru {
++	__le32 cfg_comm;
++	__le32 cfg_dl;
++	__le32 cfg_ul;
++	__le32 cfg_dbg;
++
++	struct mt7996_muru_comm comm;
++	struct mt7996_muru_dl dl;
++	struct mt7996_muru_ul ul;
++	struct mt7996_muru_dbg dbg;
++};
++
++
++#define MURU_PPDU_HE_TRIG	BIT(2)
++#define MURU_PPDU_HE_MU		BIT(3)
++
++#define MURU_OFDMA_SCH_TYPE_DL	BIT(0)
++#define MURU_OFDMA_SCH_TYPE_UL	BIT(1)
++
++/* Common Config */
++#define MURU_COMM_PPDU_FMT	BIT(0)
++#define MURU_COMM_SCH_TYPE	BIT(1)
++#define MURU_COMM_BAND		BIT(2)
++#define MURU_COMM_WMM		BIT(3)
++#define MURU_COMM_SPE_IDX	BIT(4)
++#define MURU_COMM_PROC_TYPE	BIT(5)
++#define MURU_COMM_SET		(MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE)
++#define MURU_COMM_SET_TM	(MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \
++				 MURU_COMM_WMM | MURU_COMM_SPE_IDX)
++
++/* DL Common config */
++#define MURU_FIXED_DL_TOTAL_USER_CNT	BIT(4)
++
++/* UL Common Config */
++#define MURU_FIXED_UL_TOTAL_USER_CNT	BIT(4)
++
++enum {
++	CAPI_SU,
++	CAPI_MU,
++	CAPI_ER_SU,
++	CAPI_TB,
++	CAPI_LEGACY
++};
++
++enum {
++	CAPI_BASIC,
++	CAPI_BRP,
++	CAPI_MU_BAR,
++	CAPI_MU_RTS,
++	CAPI_BSRP,
++	CAPI_GCR_MU_BAR,
++	CAPI_BQRP,
++	CAPI_NDP_FRP,
++};
++
++enum {
++	MU_DL_ACK_POLICY_MU_BAR = 3,
++	MU_DL_ACK_POLICY_TF_FOR_ACK = 4,
++	MU_DL_ACK_POLICY_SU_BAR = 5,
++};
++
++enum muru_vendor_ctrl {
++	MU_CTRL_UPDATE,
++	MU_CTRL_DL_USER_CNT,
++	MU_CTRL_UL_USER_CNT,
++};
+ #endif
+ 
+ #endif
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 9ba6f00a..477c5c42 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -10,10 +10,31 @@
+ #include "vendor.h"
+ #include "mtk_mcu.h"
+ 
++#ifdef CONFIG_MTK_VENDOR
+ static const struct nla_policy
+ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
+ 	[MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
+ 	[MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_MU_CTRL_STRUCT] = {.type = NLA_BINARY },
++};
++
++static const struct nla_policy
++wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE] = {.type = NLA_U16 },
++};
++
++static const struct nla_policy
++wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
++	[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
+ };
+ 
+ static const struct nla_policy
+@@ -70,6 +91,17 @@ ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
+ 	[MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
+ };
+ 
++static const struct nla_policy
++rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF] = { .type = NLA_U8 },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG] = { .type = NLA_NESTED },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN] = { .type = NLA_U8 },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE] = { .type = NLA_U8 },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY] = { .type = NLA_U8 },
++	[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ 	u8 idx;
+ 	u8 addr[ETH_ALEN];
+@@ -84,6 +116,8 @@ static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
+ {
+ 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ 	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	struct mt7996_muru *muru;
+ 	int err;
+ 	u8 val8;
+ 	u32 val32 = 0;
+@@ -99,9 +133,17 @@ static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
+ 			 FIELD_PREP(RATE_CFG_VAL, val8);
+ 		ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+ 							   mt7996_set_wireless_vif, &val32);
++	} else if (tb[MTK_VENDOR_ATTR_MU_CTRL_STRUCT]) {
++		muru = kzalloc(sizeof(struct mt7996_muru), GFP_KERNEL);
++
++		nla_memcpy(muru, tb[MTK_VENDOR_ATTR_MU_CTRL_STRUCT],
++			   sizeof(struct mt7996_muru));
++
++		err = mt7996_mcu_set_muru_cfg(phy, muru);
++		kfree(muru);
+ 	}
+ 
+-	return 0;
++	return err;
+ }
+ 
+ static int
+@@ -124,6 +166,48 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return len;
+ }
+ 
++void mt7996_set_wireless_rts_sigta(struct ieee80211_hw *hw, u8 value) {
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++
++	switch (value) {
++	case BW_SIGNALING_STATIC:
++	case BW_SIGNALING_DYNAMIC:
++		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_RTS_SIGTA_EN, true);
++		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_DIS_SECCH_CCA_DET, false);
++		break;
++	default:
++		value = BW_SIGNALING_DISABLE;
++		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_RTS_SIGTA_EN, false);
++		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_DIS_SECCH_CCA_DET, true);
++		break;
++      }
++
++	phy->rts_bw_sig = value;
++
++	/* Set RTS Threshold to a lower Value */
++	mt7996_mcu_set_rts_thresh(phy, 500);
++}
++
++static int
++mt7996_vendor_wireless_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);
++	int len = 0;
++
++	if (*storage == 1)
++		return -ENOENT;
++	*storage = 1;
++
++	if (nla_put_u8(skb, MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
++		       ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU)))
++	return -ENOMEM;
++	len += 1;
++
++	return len;
++ }
++
+ void mt7996_vendor_amnt_fill_rx(struct mt7996_phy *phy, struct sk_buff *skb)
+ {
+ 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+@@ -647,6 +731,126 @@ mt7996_vendor_ibf_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return 1;
+ }
+ 
++static int mt7996_vendor_rfeature_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_RFEATURE_CTRL];
++	int err;
++	u32 val;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX, data, data_len,
++			rfeature_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	val = CAPI_RFEATURE_CHANGED;
++
++	if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG]) {
++		u8 enable, trig_type;
++		int rem;
++		struct nlattr *cur;
++
++		nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG], rem) {
++			switch (nla_type(cur)) {
++			case MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN:
++				enable = nla_get_u8(cur);
++				break;
++			case MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE:
++				trig_type = nla_get_u8(cur);
++				break;
++			default:
++				return -EINVAL;
++			};
++		}
++
++		err = mt7996_mcu_set_rfeature_trig_type(phy, enable, trig_type);
++		if (err)
++			return err;
++	} else if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY]) {
++		u8 ack_policy;
++
++		ack_policy = nla_get_u8(tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY]);
++		switch (ack_policy) {
++		case MU_DL_ACK_POLICY_TF_FOR_ACK:
++			return mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_MUDL_ACK_POLICY,
++						       ack_policy);
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
++static int mt7996_vendor_wireless_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_WIRELESS_CTRL];
++	int err;
++	u8 val8;
++	u16 val16;
++	u32 val32;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX, data, data_len,
++			wireless_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	val32 = CAPI_WIRELESS_CHANGED;
++
++	if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA]);
++		val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_OFDMA) |
++			 FIELD_PREP(RATE_CFG_VAL, val8);
++		ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
++			mt7996_set_wireless_vif, &val32);
++		if (val8 == 3) /* DL20and80 */
++			mt7996_mcu_set_muru_cmd(dev, UNI_CMD_MURU_SET_20M_DYN_ALGO, 1);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE]) {
++		val16 = nla_get_u16(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE]);
++		hw->max_tx_aggregation_subframes = val16;
++		hw->max_rx_aggregation_subframes = val16;
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE]);
++		mt7996_mcu_set_ppdu_tx_type(phy, val8);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA]);
++		if (phy->muru_onoff & OFDMA_UL)
++			mt7996_mcu_set_nusers_ofdma(phy, MU_CTRL_UL_USER_CNT, val8);
++		else
++			mt7996_mcu_set_nusers_ofdma(phy, MU_CTRL_DL_USER_CNT, val8);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO]);
++		val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_MIMO) |
++			 FIELD_PREP(RATE_CFG_VAL, val8);
++		ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
++			mt7996_set_wireless_vif, &val32);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]);
++		dev->cert_mode = val8;
++		mt7996_mcu_set_cert(phy, val8);
++		mt7996_mcu_set_bypass_smthint(phy, val8);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU]);
++		mt7996_set_wireless_amsdu(hw, val8);
++	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA]);
++		mt7996_set_wireless_rts_sigta(hw, val8);
++	}
++
++	return 0;
++}
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -660,6 +864,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = mu_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
+ 	},
++	{
++		.info = {
++		        .vendor_id = MTK_NL80211_VENDOR_ID,
++		        .subcmd = MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++		        WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_wireless_ctrl,
++		.dumpit = mt7996_vendor_wireless_ctrl_dump,
++		.policy = wireless_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX,
++	},
+ 	{
+ 		.info = {
+ 			.vendor_id = MTK_NL80211_VENDOR_ID,
+@@ -718,6 +934,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = ibf_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_IBF_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_rfeature_ctrl,
++		.policy = rfeature_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+@@ -727,3 +954,4 @@ void mt7996_vendor_register(struct mt7996_phy *phy)
+ 
+ 	spin_lock_init(&phy->amnt_lock);
+ }
++#endif
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 29ccc050..7011914b 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -3,8 +3,12 @@
+ 
+ #define MTK_NL80211_VENDOR_ID	0x0ce7
+ 
++#ifdef CONFIG_MTK_VENDOR
++
+ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
++	MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
++	MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
+ 	MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+ 	MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ 	MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+@@ -60,6 +64,7 @@ enum mtk_vendor_attr_mu_ctrl {
+ 
+ 	MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
+ 	MTK_VENDOR_ATTR_MU_CTRL_DUMP,
++	MTK_VENDOR_ATTR_MU_CTRL_STRUCT,
+ 
+ 	/* keep last */
+ 	NUM_MTK_VENDOR_ATTRS_MU_CTRL,
+@@ -67,6 +72,66 @@ enum mtk_vendor_attr_mu_ctrl {
+ 		NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
+ };
+ 
++enum mtk_capi_control_changed {
++	CAPI_RFEATURE_CHANGED = BIT(16),
++	CAPI_WIRELESS_CHANGED = BIT(17),
++};
++
++enum mtk_vendor_attr_rfeature_ctrl {
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL,
++	MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX =
++	NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL - 1
++};
++
++enum mtk_vendor_attr_wireless_ctrl {
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT = 9,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA, /* reserve */
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
++	MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
++};
++
++enum mtk_vendor_attr_wireless_dump {
++	MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
++
++	MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
++	MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
++		NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
++};
++
++enum bw_sig {
++	BW_SIGNALING_DISABLE,
++	BW_SIGNALING_STATIC,
++	BW_SIGNALING_DYNAMIC
++};
++
+ enum mtk_vendor_attr_mnt_ctrl {
+ 	MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC,
+ 
+@@ -138,3 +203,5 @@ enum mtk_vendor_attr_ibf_dump {
+ };
+ 
+ #endif
++
++#endif
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1033-mtk-wifi-mt76-testmode-add-testmode-bf-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1033-mtk-wifi-mt76-testmode-add-testmode-bf-support.patch
new file mode 100644
index 0000000..569965f
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1033-mtk-wifi-mt76-testmode-add-testmode-bf-support.patch
@@ -0,0 +1,1833 @@
+From 5ebdb72f481cab029434e63a70b5c16d9fd2ec64 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 6 Apr 2023 16:40:28 +0800
+Subject: [PATCH 1033/1041] mtk: wifi: mt76: testmode: add testmode bf support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Add iTest additional bf command
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+fw return Gx (5g band) ibf cal struct for both 2G and 5G ibf.
+Therefore, memcpy cannot be used for 2G ibf cal.
+https://gerrit.mediatek.inc/c/neptune/wlan_driver/logan/+/8206056
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76.h               |   5 +
+ mt76_connac_mcu.h    |   4 +-
+ mt7996/mcu.c         |   8 +-
+ mt7996/mcu.h         |  45 ++-
+ mt7996/mt7996.h      |  12 +-
+ mt7996/mtk_debugfs.c |   6 +-
+ mt7996/mtk_mcu.c     |  79 ++++-
+ mt7996/mtk_mcu.h     | 338 +++++++++++++++++++-
+ mt7996/regs.h        |   3 +
+ mt7996/testmode.c    | 744 +++++++++++++++++++++++++++++++++++++++++--
+ mt7996/testmode.h    |  19 ++
+ testmode.c           |  60 ++++
+ testmode.h           |  53 +++
+ tools/fields.c       |  37 +++
+ 14 files changed, 1354 insertions(+), 59 deletions(-)
+
+diff --git a/mt76.h b/mt76.h
+index 9e8848f7..2a7b0ed9 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -751,6 +751,11 @@ struct mt76_testmode_data {
+ 	u32 tx_time;
+ 	u32 tx_ipg;
+ 
++	u8 txbf_act;
++	u16 txbf_param[8];
++	bool is_txbf_dut;
++	bool bf_en;
++	bool bf_ever_en;
+ 	bool ibf;
+ 	bool ebf;
+ 
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 615c42b1..306e7bee 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -488,7 +488,8 @@ struct sta_rec_bf {
+ 	bool codebook75_mu;
+ 
+ 	u8 he_ltf;
+-	u8 rsv[3];
++	u8 pp_fd_val;
++	u8 rsv[2];
+ } __packed;
+ 
+ struct sta_rec_bfee {
+@@ -1267,6 +1268,7 @@ enum {
+ 	MCU_UNI_CMD_VOW = 0x37,
+ 	MCU_UNI_CMD_PP = 0x38,
+ 	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
++	MCU_UNI_CMD_TESTMODE_TRX_PARAM = 0x42,
+ 	MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
+ 	MCU_UNI_CMD_PRECAL_RESULT = 0x47,
+ 	MCU_UNI_CMD_RRO = 0x57,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 7f235f91..6ba9c9d5 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1067,7 +1067,12 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 	bss->hw_bss_idx = idx;
+ 
+ 	if (vif->type == NL80211_IFTYPE_MONITOR) {
+-		memcpy(bss->bssid, phy->macaddr, ETH_ALEN);
++		struct mt76_testmode_data *td = &phy->test;
++
++		if (!td->bf_en)
++			memcpy(bss->bssid, phy->macaddr, ETH_ALEN);
++		else
++			memcpy(bss->bssid, td->addr[2], ETH_ALEN);
+ 		return 0;
+ 	}
+ 
+@@ -4103,7 +4108,6 @@ int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
+ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
+ {
+ #define MT7996_BF_MAX_SIZE	sizeof(union bf_tag_tlv)
+-#define BF_PROCESSING	4
+ 	struct uni_header hdr;
+ 	struct sk_buff *skb;
+ 	struct tlv *tlv;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index af078edd..054a616b 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -685,6 +685,22 @@ struct bf_sounding_on {
+ 	__le32 snd_period;
+ } __packed;
+ 
++enum sounding_mode {
++	SU_SOUNDING,
++	MU_SOUNDING,
++	SU_PERIODIC_SOUNDING,
++	MU_PERIODIC_SOUNDING,
++	BF_PROCESSING,
++	TXCMD_NONTB_SU_SOUNDING,
++	TXCMD_VHT_MU_SOUNDING,
++	TXCMD_TB_PER_BRP_SOUNDING,
++	TXCMD_TB_SOUNDING,
++
++	/* keep last */
++	NUM_SOUNDING_MODE,
++	SOUNDING_MODE_MAX = NUM_SOUNDING_MODE - 1,
++};
++
+ struct bf_hw_en_status_update {
+ 	__le16 tag;
+ 	__le16 len;
+@@ -710,6 +726,24 @@ union bf_tag_tlv {
+ 	struct bf_mod_en_ctrl bf_mod_en;
+ };
+ 
++enum {
++	BF_SOUNDING_OFF = 0,
++	BF_SOUNDING_ON = 1,
++	BF_DATA_PACKET_APPLY = 2,
++	BF_PFMU_TAG_READ = 5,
++	BF_PFMU_TAG_WRITE = 6,
++	BF_STA_REC_READ = 11,
++	BF_PHASE_CALIBRATION = 12,
++	BF_IBF_PHASE_COMP = 13,
++	BF_PROFILE_WRITE_20M_ALL = 15,
++	BF_HW_EN_UPDATE = 17,
++	BF_MOD_EN_CTRL = 20,
++	BF_FBRPT_DBG_INFO_READ = 23,
++	BF_TXSND_INFO = 24,
++	BF_CMD_TXCMD = 27,
++	BF_CFG_PHY = 28,
++};
++
+ struct ra_rate {
+ 	__le16 wlan_idx;
+ 	u8 mode;
+@@ -771,17 +805,6 @@ enum {
+ #define MUMIMO_UL                      BIT(3)
+ #define MUMIMO_DL_CERT                 BIT(4)
+ 
+-enum {
+-	BF_SOUNDING_ON = 1,
+-	BF_PFMU_TAG_READ = 5,
+-	BF_STA_REC_READ = 11,
+-	BF_HW_EN_UPDATE = 17,
+-	BF_MOD_EN_CTRL = 20,
+-	BF_FBRPT_DBG_INFO_READ = 23,
+-	BF_TXSND_INFO = 24,
+-	BF_CFG_PHY = 28,
+-};
+-
+ enum {
+ 	CMD_BAND_NONE,
+ 	CMD_BAND_24G,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index e1a191ec..b5ce4a55 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -479,6 +479,14 @@ struct mt7996_dev {
+ #ifdef CONFIG_MTK_VENDOR
+ 	bool cert_mode;
+ #endif
++
++#if defined CONFIG_NL80211_TESTMODE || defined CONFIG_MTK_DEBUG
++	struct {
++		void *txbf_phase_cal;
++		void *txbf_pfmu_data;
++		void *txbf_pfmu_tag;
++	} test;
++#endif
+ };
+ 
+ enum {
+@@ -818,7 +826,7 @@ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
+ 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);
+-int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx);
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx, bool bfer);
+ void mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val);
+ int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para);
+@@ -830,10 +838,12 @@ int mt7996_mcu_set_rfeature_trig_type(struct mt7996_phy *phy, u8 enable, u8 trig
+ void mt7996_mcu_set_ppdu_tx_type(struct mt7996_phy *phy, u8 ppdu_type);
+ void mt7996_mcu_set_nusers_ofdma(struct mt7996_phy *phy, u8 type, u8 ofdma_user_cnt);
+ void mt7996_mcu_set_cert(struct mt7996_phy *phy, u8 type);
++void mt7996_tm_update_channel(struct mt7996_phy *phy);
+ #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/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 1530ad79..0fdb911d 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2803,7 +2803,7 @@ mt7996_starec_bf_read_set(void *data, u64 wlan_idx)
+ {
+ 	struct mt7996_phy *phy = data;
+ 
+-	return mt7996_mcu_set_txbf_internal(phy, BF_STA_REC_READ, wlan_idx);
++	return mt7996_mcu_set_txbf_internal(phy, BF_STA_REC_READ, wlan_idx, 0);
+ }
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_starec_bf_read, NULL,
+ 			 mt7996_starec_bf_read_set, "%lld\n");
+@@ -2847,7 +2847,7 @@ mt7996_bf_fbk_rpt_set(void *data, u64 wlan_idx)
+ {
+ 	struct mt7996_phy *phy = data;
+ 
+-	return mt7996_mcu_set_txbf_internal(phy, BF_FBRPT_DBG_INFO_READ, wlan_idx);
++	return mt7996_mcu_set_txbf_internal(phy, BF_FBRPT_DBG_INFO_READ, wlan_idx, 0);
+ }
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_fbk_rpt, NULL,
+ 			 mt7996_bf_fbk_rpt_set, "%lld\n");
+@@ -2857,7 +2857,7 @@ mt7996_bf_pfmu_tag_read_set(void *data, u64 wlan_idx)
+ {
+ 	struct mt7996_phy *phy = data;
+ 
+-	return mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, wlan_idx);
++	return mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, wlan_idx, 1);
+ }
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_pfmu_tag_read, NULL,
+ 			 mt7996_bf_pfmu_tag_read_set, "%lld\n");
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index 3b8fbe42..2d8b08cd 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -296,7 +296,7 @@ __mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len)
+ 	return ptlv;
+ }
+ 
+-int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx)
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx, bool bfer)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+ #define MT7996_MTK_BF_MAX_SIZE	sizeof(struct bf_starec_read)
+@@ -319,9 +319,8 @@ int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx)
+ 
+ 		tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
+ 		req = (struct bf_pfmu_tag *)tlv;
+-#define BFER 1
+ 		req->pfmu_id = idx;
+-		req->bfer = BFER;
++		req->bfer = bfer;
+ 		req->band_idx = phy->mt76->band_idx;
+ 		break;
+ 	}
+@@ -433,10 +432,36 @@ int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para)
+ 	return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, MCU_WM_UNI_CMD(BF), false);
+ }
+ 
++static inline void
++mt7996_ibf_phase_assign(struct mt7996_dev *dev,
++			struct mt7996_ibf_cal_info *cal,
++			struct mt7996_txbf_phase *phase)
++{
++	/* fw return ibf calibrated data with
++	 * the mt7996_txbf_phase_info_5g struct for both 2G and 5G.
++	 * Therefore, memcpy cannot be used here.
++	 */
++	phase_assign(cal->group, m_t0_h, true);
++	phase_assign(cal->group, m_t1_h, true);
++	phase_assign(cal->group, m_t2_h, true);
++	phase_assign(cal->group, m_t2_h_sx2, false);
++	phase_assign_rx(cal->group, r0);
++	phase_assign_rx(cal->group, r1);
++	phase_assign_rx(cal->group, r2);
++	phase_assign_rx(cal->group, r3);
++	phase_assign_rx_g0(cal->group, r2_sx2);
++	phase_assign_rx_g0(cal->group, r3_sx2);
++	phase_assign(cal->group, r0_reserved, false);
++	phase_assign(cal->group, r1_reserved, false);
++	phase_assign(cal->group, r2_reserved, false);
++	phase_assign(cal->group, r3_reserved, false);
++	phase_assign(cal->group, r2_sx2_reserved, false);
++	phase_assign(cal->group, r3_sx2_reserved, false);
++}
++
+ void
+ mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+-#define HE_MODE 3
+ 	struct mt7996_mcu_bf_basic_event *event;
+ 
+ 	event = (struct mt7996_mcu_bf_basic_event *)skb->data;
+@@ -471,13 +496,12 @@ mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 			 tag->t1.nr, tag->t1.nc, tag->t1.ngroup, tag->t1.lm, tag->t1.codebook,
+ 			 tag->t1.mob_cal_en);
+ 
+-		if (tag->t1.lm <= HE_MODE) {
++		if (tag->t1.lm <= BF_LM_HE)
+ 			dev_info(dev->mt76.dev, "RU start = %d, RU end = %d\n",
+ 				 tag->t1.field.ru_start_id, tag->t1.field.ru_end_id);
+-		} else {
++		else
+ 			dev_info(dev->mt76.dev, "PartialBW = %d\n",
+ 				 tag->t1.bw_info.partial_bw_info);
+-		}
+ 
+ 		dev_info(dev->mt76.dev, "Mem Col1 = %d, Mem Row1 = %d, Mem Col2 = %d, Mem Row2 = %d\n",
+ 			 tag->t1.col_id1, tag->t1.row_id1, tag->t1.col_id2, tag->t1.row_id2);
+@@ -731,6 +755,47 @@ mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 
+ 		break;
+ 	}
++	case UNI_EVENT_BF_CAL_PHASE: {
++		struct mt7996_ibf_cal_info *cal;
++		struct mt7996_txbf_phase_out phase_out;
++		struct mt7996_txbf_phase *phase;
++
++		cal = (struct mt7996_ibf_cal_info *)skb->data;
++		phase = (struct mt7996_txbf_phase *)dev->test.txbf_phase_cal;
++		memcpy(&phase_out, &cal->phase_out, sizeof(phase_out));
++		switch (cal->cal_type) {
++		case IBF_PHASE_CAL_NORMAL:
++		case IBF_PHASE_CAL_NORMAL_INSTRUMENT:
++			/* Only calibrate group M */
++			if (cal->group_l_m_n != GROUP_M)
++				break;
++			phase = &phase[cal->group];
++			phase->status = cal->status;
++			dev_info(dev->mt76.dev, "Calibrated result = %d\n", phase->status);
++			dev_info(dev->mt76.dev, "Group %d and Group M\n", cal->group);
++			mt7996_ibf_phase_assign(dev, cal, phase);
++			break;
++		case IBF_PHASE_CAL_VERIFY:
++		case IBF_PHASE_CAL_VERIFY_INSTRUMENT:
++			dev_info(dev->mt76.dev, "Verification result = %d\n", cal->status);
++			break;
++		default:
++			break;
++		}
++
++		dev_info(dev->mt76.dev, "c0_uh = %d, c1_uh = %d, c2_uh = %d, c3_uh = %d\n",
++			 phase_out.c0_uh, phase_out.c1_uh, phase_out.c2_uh, phase_out.c3_uh);
++		dev_info(dev->mt76.dev, "c0_h = %d, c1_h = %d, c2_h = %d, c3_h = %d\n",
++			 phase_out.c0_h, phase_out.c1_h, phase_out.c2_h, phase_out.c3_h);
++		dev_info(dev->mt76.dev, "c0_mh = %d, c1_mh = %d, c2_mh = %d, c3_mh = %d\n",
++			 phase_out.c0_mh, phase_out.c1_mh, phase_out.c2_mh, phase_out.c3_mh);
++		dev_info(dev->mt76.dev, "c0_m = %d, c1_m = %d, c2_m = %d, c3_m = %d\n",
++			 phase_out.c0_m, phase_out.c1_m, phase_out.c2_m, phase_out.c3_m);
++		dev_info(dev->mt76.dev, "c0_l = %d, c1_l = %d, c2_l = %d, c3_l = %d\n",
++			 phase_out.c0_l, phase_out.c1_l, phase_out.c2_l, phase_out.c3_l);
++
++		break;
++	}
+ 	default:
+ 		dev_info(dev->mt76.dev, "%s: unknown bf event tag %d\n",
+ 			 __func__, event->tag);
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index 44cb0327..881afef1 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -176,6 +176,164 @@ struct bf_txsnd_info {
+ 	u8 __rsv[2];
+ } __packed;
+ 
++#define MAX_PHASE_GROUP_NUM	9
++
++struct bf_phase_comp {
++	__le16 tag;
++	__le16 len;
++
++	u8 bw;
++	u8 jp_band;
++	u8 band_idx;
++	bool read_from_e2p;
++	bool disable;
++	u8 group;
++	u8 rsv[2];
++	u8 buf[44];
++} __packed;
++
++struct bf_tx_apply {
++	__le16 tag;
++	__le16 len;
++
++	__le16 wlan_idx;
++	bool ebf;
++	bool ibf;
++	bool mu_txbf;
++	bool phase_cal;
++	u8 rsv[2];
++} __packed;
++
++struct bf_phase_cal {
++	__le16 tag;
++	__le16 len;
++
++	u8 group_l_m_n;
++	u8 group;
++	u8 sx2;
++	u8 cal_type;
++	u8 lna_gain_level;
++	u8 band_idx;
++	u8 rsv[2];
++} __packed;
++
++struct bf_txcmd {
++	__le16 tag;
++	__le16 len;
++
++	u8 action;
++	u8 bf_manual;
++	u8 bf_bit;
++	u8 rsv[5];
++} __packed;
++
++struct bf_pfmu_data_all {
++	__le16 tag;
++	__le16 len;
++
++	u8 pfmu_id;
++	u8 band_idx;
++	u8 rsv[2];
++
++	u8 buf[512];
++} __packed;
++
++#define TXBF_DUT_MAC_SUBADDR		0x22
++#define TXBF_GOLDEN_MAC_SUBADDR		0x11
++
++struct mt7996_tm_bf_req {
++	u8 _rsv[4];
++
++	union {
++		struct bf_sounding_on sounding;
++		struct bf_tx_apply tx_apply;
++		struct bf_pfmu_tag pfmu_tag;
++		struct bf_pfmu_data_all pfmu_data_all;
++		struct bf_phase_cal phase_cal;
++		struct bf_phase_comp phase_comp;
++		struct bf_txcmd txcmd;
++	};
++} __packed;
++
++enum tm_trx_mac_type {
++	TM_TRX_MAC_TX = 1,
++	TM_TRX_MAC_RX,
++	TM_TRX_MAC_TXRX,
++	TM_TRX_MAC_TXRX_RXV,
++	TM_TRX_MAC_RXV,
++	TM_TRX_MAC_RX_RXV,
++};
++
++enum tm_trx_param_idx {
++	TM_TRX_PARAM_RSV,
++	/* MAC */
++	TM_TRX_PARAM_SET_TRX,
++	TM_TRX_PARAM_RX_FILTER,
++	TM_TRX_PARAM_RX_FILTER_PKT_LEN,
++	TM_TRX_PARAM_SLOT_TIME,
++	TM_TRX_PARAM_CLEAN_PERSTA_TXQUEUE,
++	TM_TRX_PARAM_AMPDU_WTBL,
++	TM_TRX_PARAM_MU_RX_AID,
++	TM_TRX_PARAM_PHY_MANUAL_TX,
++
++	/* PHY */
++	TM_TRX_PARAM_RX_PATH,
++	TM_TRX_PARAM_TX_STREAM,
++	TM_TRX_PARAM_TSSI_STATUS,
++	TM_TRX_PARAM_DPD_STATUS,
++	TM_TRX_PARAM_RATE_POWER_OFFSET_ON_OFF,
++	TM_TRX_PARAM_THERMO_COMP_STATUS,
++	TM_TRX_PARAM_FREQ_OFFSET,
++	TM_TRX_PARAM_FAGC_RSSI_PATH,
++	TM_TRX_PARAM_PHY_STATUS_COUNT,
++	TM_TRX_PARAM_RXV_INDEX,
++
++	TM_TRX_PARAM_ANTENNA_PORT,
++	TM_TRX_PARAM_THERMAL_ONOFF,
++	TM_TRX_PARAM_TX_POWER_CONTROL_ALL_RF,
++	TM_TRX_PARAM_RATE_POWER_OFFSET,
++	TM_TRX_PARAM_SLT_CMD_TEST,
++	TM_TRX_PARAM_SKU,
++	TM_TRX_PARAM_POWER_PERCENTAGE_ON_OFF,
++	TM_TRX_PARAM_BF_BACKOFF_ON_OFF,
++	TM_TRX_PARAM_POWER_PERCENTAGE_LEVEL,
++	TM_TRX_PARAM_FRTBL_CFG,
++	TM_TRX_PARAM_PREAMBLE_PUNC_ON_OFF,
++
++	TM_TRX_PARAM_MAX_NUM,
++};
++
++enum trx_action {
++	TM_TRX_ACTION_SET,
++	TM_TRX_ACTION_GET,
++};
++
++struct tm_trx_set {
++	u8 type;
++	u8 enable;
++	u8 band_idx;
++	u8 rsv;
++} __packed;
++
++struct mt7996_tm_trx_req {
++	u8 param_num;
++	u8 _rsv[3];
++
++	__le16 tag;
++	__le16 len;
++
++	__le16 param_idx;
++	u8 band_idx;
++	u8 testmode_en;
++	u8 action;
++	u8 rsv[3];
++
++	u32 data;
++	struct tm_trx_set set_trx;
++
++	u8 buf[220];
++} __packed;
++
+ struct mt7996_mcu_bf_basic_event {
+ 	struct mt7996_mcu_rxd rxd;
+ 
+@@ -381,6 +539,181 @@ struct mt7996_pfmu_tag_event {
+ 	struct mt7996_pfmu_tag2 t2;
+ };
+ 
++struct mt7996_pfmu_tag {
++	struct mt7996_pfmu_tag1 t1;
++	struct mt7996_pfmu_tag2 t2;
++};
++
++enum bf_lm_type {
++	BF_LM_LEGACY,
++	BF_LM_HT,
++	BF_LM_VHT,
++	BF_LM_HE,
++	BF_LM_EHT,
++};
++
++struct mt7996_txbf_phase_out {
++	u8 c0_l;
++	u8 c1_l;
++	u8 c2_l;
++	u8 c3_l;
++	u8 c0_m;
++	u8 c1_m;
++	u8 c2_m;
++	u8 c3_m;
++	u8 c0_mh;
++	u8 c1_mh;
++	u8 c2_mh;
++	u8 c3_mh;
++	u8 c0_h;
++	u8 c1_h;
++	u8 c2_h;
++	u8 c3_h;
++	u8 c0_uh;
++	u8 c1_uh;
++	u8 c2_uh;
++	u8 c3_uh;
++};
++
++struct mt7996_txbf_rx_phase_2g {
++	u8 rx_uh;
++	u8 rx_h;
++	u8 rx_m;
++	u8 rx_l;
++	u8 rx_ul;
++};
++
++struct mt7996_txbf_rx_phase_5g {
++	u8 rx_uh;
++	u8 rx_h;
++	u8 rx_mh;
++	u8 rx_m;
++	u8 rx_l;
++	u8 rx_ul;
++};
++
++struct mt7996_txbf_phase_info_2g {
++	struct mt7996_txbf_rx_phase_2g r0;
++	struct mt7996_txbf_rx_phase_2g r1;
++	struct mt7996_txbf_rx_phase_2g r2;
++	struct mt7996_txbf_rx_phase_2g r3;
++	struct mt7996_txbf_rx_phase_2g r2_sx2;
++	struct mt7996_txbf_rx_phase_2g r3_sx2;
++	u8 m_t0_h;
++	u8 m_t1_h;
++	u8 m_t2_h;
++	u8 m_t2_h_sx2;
++	u8 r0_reserved;
++	u8 r1_reserved;
++	u8 r2_reserved;
++	u8 r3_reserved;
++	u8 r2_sx2_reserved;
++	u8 r3_sx2_reserved;
++};
++
++struct mt7996_txbf_phase_info_5g {
++	struct mt7996_txbf_rx_phase_5g r0;
++	struct mt7996_txbf_rx_phase_5g r1;
++	struct mt7996_txbf_rx_phase_5g r2;
++	struct mt7996_txbf_rx_phase_5g r3;
++	struct mt7996_txbf_rx_phase_2g r2_sx2;	/* no middle-high in r2_sx2 */
++	struct mt7996_txbf_rx_phase_2g r3_sx2;	/* no middle-high in r3_sx2 */
++	u8 m_t0_h;
++	u8 m_t1_h;
++	u8 m_t2_h;
++	u8 m_t2_h_sx2;
++	u8 r0_reserved;
++	u8 r1_reserved;
++	u8 r2_reserved;
++	u8 r3_reserved;
++	u8 r2_sx2_reserved;
++	u8 r3_sx2_reserved;
++};
++
++struct mt7996_txbf_phase {
++	u8 status;
++	union {
++		struct mt7996_txbf_phase_info_2g phase_2g;
++		struct mt7996_txbf_phase_info_5g phase_5g;
++	};
++};
++
++#define phase_assign(group, field, dump, ...)	({						\
++	if (group) {										\
++		phase->phase_5g.field = cal->phase_5g.field;					\
++		if (dump)									\
++			dev_info(dev->mt76.dev, "%s = %d\n", #field, phase->phase_5g.field);	\
++	} else {										\
++		phase->phase_2g.field = cal->phase_5g.field;					\
++		if (dump)									\
++			dev_info(dev->mt76.dev, "%s = %d\n", #field, phase->phase_2g.field);	\
++	}											\
++})
++
++#define phase_assign_rx_g0(group, rx, ...)	({						\
++	phase_assign(group, rx.rx_uh, false);							\
++	phase_assign(group, rx.rx_h, false);							\
++	phase_assign(group, rx.rx_m, false);							\
++	phase_assign(group, rx.rx_l, false);							\
++	phase_assign(group, rx.rx_ul, false);							\
++})
++
++#define phase_assign_rx(group, rx, ...)	({							\
++	if (group) {										\
++		phase_assign(group, rx.rx_uh, true);						\
++		phase_assign(group, rx.rx_h, true);						\
++		phase->phase_5g.rx.rx_mh = cal->phase_5g.rx.rx_mh;				\
++		dev_info(dev->mt76.dev, "%s.rx_mh = %d\n", #rx, phase->phase_5g.rx.rx_mh);	\
++		phase_assign(group, rx.rx_m, true);						\
++		phase_assign(group, rx.rx_l, true);						\
++		phase_assign(group, rx.rx_ul, true);						\
++	} else {										\
++		phase_assign(group, rx.rx_uh, true);						\
++		phase_assign(group, rx.rx_h, true);						\
++		phase_assign(group, rx.rx_m, true);						\
++		phase_assign(group, rx.rx_l, true);						\
++		phase_assign(group, rx.rx_ul, true);						\
++	}											\
++})
++
++#define GROUP_L		0
++#define GROUP_M		1
++#define GROUP_H		2
++
++struct mt7996_pfmu_data {
++	__le16 subc_idx;
++	__le16 phi11;
++	__le16 phi21;
++	__le16 phi31;
++};
++
++struct mt7996_ibf_cal_info {
++	struct mt7996_mcu_bf_basic_event event;
++
++	u8 category_id;
++	u8 group_l_m_n;
++	u8 group;
++	bool sx2;
++	u8 status;
++	u8 cal_type;
++	u8 _rsv[2];
++	struct mt7996_txbf_phase_out phase_out;
++	union {
++		struct mt7996_txbf_phase_info_2g phase_2g;
++		struct mt7996_txbf_phase_info_5g phase_5g;
++	};
++} __packed;
++
++enum {
++	IBF_PHASE_CAL_UNSPEC,
++	IBF_PHASE_CAL_NORMAL,
++	IBF_PHASE_CAL_VERIFY,
++	IBF_PHASE_CAL_NORMAL_INSTRUMENT,
++	IBF_PHASE_CAL_VERIFY_INSTRUMENT,
++};
++
++#define MT7996_TXBF_SUBCAR_NUM	64
++
+ enum {
+ 	UNI_EVENT_BF_PFMU_TAG = 0x5,
+ 	UNI_EVENT_BF_PFMU_DATA = 0x7,
+@@ -395,11 +728,6 @@ enum {
+ 	UNI_EVENT_BF_MAX_NUM
+ };
+ 
+-enum {
+-	UNI_CMD_MURU_FIXED_RATE_CTRL = 0x11,
+-	UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
+-};
+-
+ struct uni_muru_mum_set_group_tbl_entry {
+ 	__le16 wlan_idx0;
+ 	__le16 wlan_idx1;
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index e94f9a90..aa04d8d2 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -326,6 +326,9 @@ enum offs_rev {
+ #define MT_ARB_SCR_TX_DISABLE			BIT(8)
+ #define MT_ARB_SCR_RX_DISABLE			BIT(9)
+ 
++#define MT_ARB_TQSAXM0(_band)			MT_WF_ARB(_band, 0x180)
++#define MT_ARB_TQSAXM_ALTX_START_MASK		GENMASK(12, 8)
++
+ /* RMAC: band 0(0x820e5000), band 1(0x820f5000), band 2(0x830e5000), */
+ #define MT_WF_RMAC_BASE(_band)			__BASE(WF_RMAC_BASE, (_band))
+ #define MT_WF_RMAC(_band, ofs)			(MT_WF_RMAC_BASE(_band) + (ofs))
+diff --git a/mt7996/testmode.c b/mt7996/testmode.c
+index 26ae5827..2fb36a97 100644
+--- a/mt7996/testmode.c
++++ b/mt7996/testmode.c
+@@ -23,6 +23,7 @@ enum {
+ 	TM_CHANGED_IPI_THRESHOLD,
+ 	TM_CHANGED_IPI_PERIOD,
+ 	TM_CHANGED_IPI_RESET,
++	TM_CHANGED_TXBF_ACT,
+ 
+ 	/* must be last */
+ 	NUM_TM_CHANGED
+@@ -41,25 +42,31 @@ static const u8 tm_change_map[] = {
+ 	[TM_CHANGED_IPI_THRESHOLD] = MT76_TM_ATTR_IPI_THRESHOLD,
+ 	[TM_CHANGED_IPI_PERIOD] = MT76_TM_ATTR_IPI_PERIOD,
+ 	[TM_CHANGED_IPI_RESET] = MT76_TM_ATTR_IPI_RESET,
++	[TM_CHANGED_TXBF_ACT] = MT76_TM_ATTR_TXBF_ACT,
+ };
+ 
+ static void mt7996_tm_ipi_work(struct work_struct *work);
++static int mt7996_tm_txbf_apply_tx(struct mt7996_phy *phy, u16 wlan_idx,
++				   bool ebf, bool ibf, bool phase_cal);
+ 
+ static u32 mt7996_tm_bw_mapping(enum nl80211_chan_width width, enum bw_mapping_method method)
+ {
+ 	static const u32 width_to_bw[][NUM_BW_MAP] = {
+-		[NL80211_CHAN_WIDTH_40] = {FW_CDBW_40MHZ, TM_CBW_40MHZ, 40,
++		[NL80211_CHAN_WIDTH_40] = {FW_CDBW_40MHZ, TM_CBW_40MHZ, BF_CDBW_40MHZ, 40,
+ 					   FIRST_CONTROL_CHAN_BITMAP_BW40},
+-		[NL80211_CHAN_WIDTH_80] = {FW_CDBW_80MHZ, TM_CBW_80MHZ, 80,
++		[NL80211_CHAN_WIDTH_80] = {FW_CDBW_80MHZ, TM_CBW_80MHZ, BF_CDBW_80MHZ, 80,
+ 					   FIRST_CONTROL_CHAN_BITMAP_BW80},
+-		[NL80211_CHAN_WIDTH_80P80] = {FW_CDBW_8080MHZ, TM_CBW_8080MHZ, 80, 0x0},
+-		[NL80211_CHAN_WIDTH_160] = {FW_CDBW_160MHZ, TM_CBW_160MHZ, 160,
++		[NL80211_CHAN_WIDTH_80P80] = {FW_CDBW_8080MHZ, TM_CBW_8080MHZ, BF_CDBW_8080MHZ,
++					      80, 0x0},
++		[NL80211_CHAN_WIDTH_160] = {FW_CDBW_160MHZ, TM_CBW_160MHZ, BF_CDBW_160MHZ, 160,
+ 					    FIRST_CONTROL_CHAN_BITMAP_BW160},
+-		[NL80211_CHAN_WIDTH_5] = {FW_CDBW_5MHZ, TM_CBW_5MHZ, 5, 0x0},
+-		[NL80211_CHAN_WIDTH_10] = {FW_CDBW_10MHZ, TM_CBW_10MHZ, 10, 0x0},
+-		[NL80211_CHAN_WIDTH_20] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, 20, 0x0},
+-		[NL80211_CHAN_WIDTH_20_NOHT] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, 20, 0x0},
+-		[NL80211_CHAN_WIDTH_320] = {FW_CDBW_320MHZ, TM_CBW_320MHZ, 320, 0x0},
++		[NL80211_CHAN_WIDTH_5] = {FW_CDBW_5MHZ, TM_CBW_5MHZ, BF_CDBW_5MHZ, 5, 0x0},
++		[NL80211_CHAN_WIDTH_10] = {FW_CDBW_10MHZ, TM_CBW_10MHZ, BF_CDBW_10MHZ, 10, 0x0},
++		[NL80211_CHAN_WIDTH_20] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, BF_CDBW_20MHZ, 20, 0x0},
++		[NL80211_CHAN_WIDTH_20_NOHT] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, BF_CDBW_20MHZ,
++						20, 0x0},
++		[NL80211_CHAN_WIDTH_320] = {FW_CDBW_320MHZ, TM_CBW_320MHZ, BF_CDBW_320MHZ,
++					    320, 0x0},
+ 	};
+ 
+ 	if (width >= ARRAY_SIZE(width_to_bw))
+@@ -68,26 +75,26 @@ static u32 mt7996_tm_bw_mapping(enum nl80211_chan_width width, enum bw_mapping_m
+ 	return width_to_bw[width][method];
+ }
+ 
+-static u8 mt7996_tm_rate_to_phy(u8 tx_rate_mode)
++static u8 mt7996_tm_rate_mapping(u8 tx_rate_mode, enum rate_mapping_type type)
+ {
+-	static const u8 rate_to_phy[] = {
+-		[MT76_TM_TX_MODE_CCK] = MT_PHY_TYPE_CCK,
+-		[MT76_TM_TX_MODE_OFDM] = MT_PHY_TYPE_OFDM,
+-		[MT76_TM_TX_MODE_HT] = MT_PHY_TYPE_HT,
+-		[MT76_TM_TX_MODE_VHT] = MT_PHY_TYPE_VHT,
+-		[MT76_TM_TX_MODE_HE_SU] = MT_PHY_TYPE_HE_SU,
+-		[MT76_TM_TX_MODE_HE_EXT_SU] = MT_PHY_TYPE_HE_EXT_SU,
+-		[MT76_TM_TX_MODE_HE_TB] = MT_PHY_TYPE_HE_TB,
+-		[MT76_TM_TX_MODE_HE_MU] = MT_PHY_TYPE_HE_MU,
+-		[MT76_TM_TX_MODE_EHT_SU] = MT_PHY_TYPE_EHT_SU,
+-		[MT76_TM_TX_MODE_EHT_TRIG] = MT_PHY_TYPE_EHT_TRIG,
+-		[MT76_TM_TX_MODE_EHT_MU] = MT_PHY_TYPE_EHT_MU,
++	static const u8 rate_to_phy[][NUM_RATE_MAP] = {
++		[MT76_TM_TX_MODE_CCK] = {MT_PHY_TYPE_CCK, BF_LM_LEGACY},
++		[MT76_TM_TX_MODE_OFDM] = {MT_PHY_TYPE_OFDM, BF_LM_LEGACY},
++		[MT76_TM_TX_MODE_HT] = {MT_PHY_TYPE_HT, BF_LM_HT},
++		[MT76_TM_TX_MODE_VHT] = {MT_PHY_TYPE_VHT, BF_LM_VHT},
++		[MT76_TM_TX_MODE_HE_SU] = {MT_PHY_TYPE_HE_SU, BF_LM_HE},
++		[MT76_TM_TX_MODE_HE_EXT_SU] = {MT_PHY_TYPE_HE_EXT_SU, BF_LM_HE},
++		[MT76_TM_TX_MODE_HE_TB] = {MT_PHY_TYPE_HE_TB, BF_LM_HE},
++		[MT76_TM_TX_MODE_HE_MU] = {MT_PHY_TYPE_HE_MU, BF_LM_HE},
++		[MT76_TM_TX_MODE_EHT_SU] = {MT_PHY_TYPE_EHT_SU, BF_LM_EHT},
++		[MT76_TM_TX_MODE_EHT_TRIG] = {MT_PHY_TYPE_EHT_TRIG, BF_LM_EHT},
++		[MT76_TM_TX_MODE_EHT_MU] = {MT_PHY_TYPE_EHT_MU, BF_LM_EHT},
+ 	};
+ 
+ 	if (tx_rate_mode > MT76_TM_TX_MODE_MAX)
+ 		return -EINVAL;
+ 
+-	return rate_to_phy[tx_rate_mode];
++	return rate_to_phy[tx_rate_mode][type];
+ }
+ 
+ static int
+@@ -239,7 +246,7 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en)
+ 		INIT_DELAYED_WORK(&phy->ipi_work, mt7996_tm_ipi_work);
+ }
+ 
+-static void
++void
+ mt7996_tm_update_channel(struct mt7996_phy *phy)
+ {
+ #define CHAN_FREQ_BW_80P80_TAG		(SET_ID(CHAN_FREQ) | BIT(16))
+@@ -303,7 +310,8 @@ mt7996_tm_set_tx_frames(struct mt7996_phy *phy, bool en)
+ 		mt7996_tm_set(dev, SET_ID(MAC_HEADER), FRAME_CONTROL);
+ 		mt7996_tm_set(dev, SET_ID(SEQ_CTRL), 0);
+ 		mt7996_tm_set(dev, SET_ID(TX_COUNT), td->tx_count);
+-		mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
++		mt7996_tm_set(dev, SET_ID(TX_MODE),
++			      mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY));
+ 		mt7996_tm_set(dev, SET_ID(TX_RATE), td->tx_rate_idx);
+ 
+ 		if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER))
+@@ -331,7 +339,8 @@ mt7996_tm_set_tx_frames(struct mt7996_phy *phy, bool en)
+ 
+ 		mt7996_tm_set(dev, SET_ID(MAX_PE), 2);
+ 		mt7996_tm_set(dev, SET_ID(HW_TX_MODE), 0);
+-		mt7996_tm_update_channel(phy);
++		if (!td->bf_en)
++			mt7996_tm_update_channel(phy);
+ 
+ 		/* trigger firmware to start TX */
+ 		mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(START_TX));
+@@ -373,7 +382,8 @@ mt7996_tm_set_rx_frames(struct mt7996_phy *phy, bool en)
+ 			return;
+ 		}
+ 
+-		mt7996_tm_update_channel(phy);
++		if (!td->bf_en)
++			mt7996_tm_update_channel(phy);
+ 
+ 		if (td->tx_rate_mode >= MT76_TM_TX_MODE_HE_MU) {
+ 			if (td->aid)
+@@ -381,7 +391,8 @@ mt7996_tm_set_rx_frames(struct mt7996_phy *phy, bool en)
+ 			else
+ 				ret = mt7996_tm_set(dev, SET_ID(RX_MU_AID), RX_MU_DISABLE);
+ 		}
+-		mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
++		mt7996_tm_set(dev, SET_ID(TX_MODE),
++			      mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY));
+ 		mt7996_tm_set(dev, SET_ID(GI), td->tx_rate_sgi);
+ 		mt7996_tm_set_antenna(phy, SET_ID(RX_PATH));
+ 		mt7996_tm_set(dev, SET_ID(MAX_PE), 2);
+@@ -405,7 +416,8 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
+ 
+ 	if (en) {
+ 		mt7996_tm_update_channel(phy);
+-		mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
++		mt7996_tm_set(dev, SET_ID(TX_MODE),
++			      mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY));
+ 		mt7996_tm_set(dev, SET_ID(TX_RATE), td->tx_rate_idx);
+ 		/* fix payload is OFDM */
+ 		mt7996_tm_set(dev, SET_ID(CONT_WAVE_MODE), CONT_WAVE_MODE_OFDM);
+@@ -1047,6 +1059,678 @@ mt7996_tm_set_ipi(struct mt7996_phy *phy)
+ 	return 0;
+ }
+ 
++static int
++mt7996_tm_set_trx_mac(struct mt7996_phy *phy, u8 type, bool en)
++{
++#define UNI_TM_TRX_CTRL 0
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_trx_req req = {
++		.param_num = 1,
++		.tag = cpu_to_le16(UNI_TM_TRX_CTRL),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.param_idx = cpu_to_le16(TM_TRX_PARAM_SET_TRX),
++		.band_idx = phy->mt76->band_idx,
++		.testmode_en = 1,
++		.action = TM_TRX_ACTION_SET,
++		.set_trx = {
++			.type = type,
++			.enable = en,
++			.band_idx = phy->mt76->band_idx,
++		}
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_TRX_PARAM),
++				 &req, sizeof(req), false);
++}
++
++static int
++mt7996_tm_txbf_init(struct mt7996_phy *phy, u16 *val)
++{
++#define EBF_BBP_RX_OFFSET	0x10280
++#define EBF_BBP_RX_ENABLE	(BIT(0) | BIT(15))
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	bool enable = val[0];
++	void *phase_cal, *pfmu_data, *pfmu_tag;
++	u8 nss, band_idx = phy->mt76->band_idx;
++	enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20;
++	u8 sub_addr = td->is_txbf_dut ? TXBF_DUT_MAC_SUBADDR : TXBF_GOLDEN_MAC_SUBADDR;
++	u8 peer_addr = td->is_txbf_dut ? TXBF_GOLDEN_MAC_SUBADDR : TXBF_DUT_MAC_SUBADDR;
++	u8 bss_addr = TXBF_DUT_MAC_SUBADDR;
++	u8 addr[ETH_ALEN] = {0x00, sub_addr, sub_addr, sub_addr, sub_addr, sub_addr};
++	u8 bssid[ETH_ALEN] = {0x00, bss_addr, bss_addr, bss_addr, bss_addr, bss_addr};
++	u8 peer_addrs[ETH_ALEN] = {0x00, peer_addr, peer_addr, peer_addr, peer_addr, peer_addr};
++	struct mt7996_vif *mvif = (struct mt7996_vif *)phy->monitor_vif->drv_priv;
++
++	if (!enable) {
++		td->bf_en = false;
++		return 0;
++	}
++
++	if (!dev->test.txbf_phase_cal) {
++		phase_cal = devm_kzalloc(dev->mt76.dev,
++					 sizeof(struct mt7996_txbf_phase) *
++					 MAX_PHASE_GROUP_NUM,
++					 GFP_KERNEL);
++		if (!phase_cal)
++			return -ENOMEM;
++
++		dev->test.txbf_phase_cal = phase_cal;
++	}
++
++	if (!dev->test.txbf_pfmu_data) {
++		pfmu_data = devm_kzalloc(dev->mt76.dev,
++					 sizeof(struct mt7996_pfmu_data) *
++					 MT7996_TXBF_SUBCAR_NUM,
++					 GFP_KERNEL);
++		if (!pfmu_data)
++			return -ENOMEM;
++
++		dev->test.txbf_pfmu_data = pfmu_data;
++	}
++
++	if (!dev->test.txbf_pfmu_tag) {
++		pfmu_tag = devm_kzalloc(dev->mt76.dev,
++					sizeof(struct mt7996_pfmu_tag), GFP_KERNEL);
++		if (!pfmu_tag)
++			return -ENOMEM;
++
++		dev->test.txbf_pfmu_tag = pfmu_tag;
++	}
++
++	td->bf_en = true;
++	dev->ibf = td->ibf;
++	memcpy(td->addr[0], peer_addrs, ETH_ALEN);
++	memcpy(td->addr[1], addr, ETH_ALEN);
++	memcpy(td->addr[2], bssid, ETH_ALEN);
++	memcpy(phy->monitor_vif->addr, addr, ETH_ALEN);
++	mt7996_tm_set_mac_addr(dev, td->addr[0], SET_ID(DA));
++	mt7996_tm_set_mac_addr(dev, td->addr[1], SET_ID(SA));
++	mt7996_tm_set_mac_addr(dev, td->addr[2], SET_ID(BSSID));
++
++	/* bss idx & omac idx should be set to band idx for ibf cal */
++	mvif->mt76.idx = band_idx;
++	dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
++	mvif->mt76.omac_idx = band_idx;
++	phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
++
++	mt7996_mcu_add_dev_info(phy, phy->monitor_vif, true);
++	mt7996_mcu_add_bss_info(phy, phy->monitor_vif, true);
++
++	if (td->ibf) {
++		if (td->is_txbf_dut) {
++			/* Enable ITxBF Capability */
++			mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
++			mt7996_tm_set_trx_mac(phy, TM_TRX_MAC_TX, true);
++
++			td->tx_ipg = 999;
++			td->tx_mpdu_len = 1024;
++			td->tx_antenna_mask = phy->mt76->chainmask >> dev->chainshift[band_idx];
++			nss = hweight8(td->tx_antenna_mask);
++			if (nss > 1 && nss <= 4)
++				td->tx_rate_idx = 15 + 8 * (nss - 2);
++			else
++				td->tx_rate_idx = 31;
++		} else {
++			td->tx_antenna_mask = 1;
++			td->tx_mpdu_len = 1024;
++			td->tx_rate_idx = 0;
++			mt76_set(dev, EBF_BBP_RX_OFFSET, EBF_BBP_RX_ENABLE);
++			dev_info(dev->mt76.dev, "Set BBP RX CR = %x\n",
++				 mt76_rr(dev, EBF_BBP_RX_OFFSET));
++		}
++
++		td->tx_rate_mode = MT76_TM_TX_MODE_HT;
++		td->tx_rate_sgi = 0;
++	} else {
++		if (td->is_txbf_dut) {
++			/* Enable ETxBF Capability */
++			mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
++			td->tx_antenna_mask = phy->mt76->chainmask >> dev->chainshift[band_idx];
++			td->tx_spe_idx = 24 + phy->mt76->band_idx;
++			if (td->tx_rate_mode == MT76_TM_TX_MODE_VHT ||
++			    td->tx_rate_mode == MT76_TM_TX_MODE_HE_SU)
++				mt7996_tm_set(dev, SET_ID(NSS), td->tx_rate_nss);
++
++			mt7996_tm_set(dev, SET_ID(ENCODE_MODE), td->tx_rate_ldpc);
++			mt7996_tm_set(dev, SET_ID(TX_COUNT), td->tx_count);
++		} else {
++			/* Turn On BBP CR for RX */
++			mt76_set(dev, EBF_BBP_RX_OFFSET, EBF_BBP_RX_ENABLE);
++			dev_info(dev->mt76.dev, "Set BBP RX CR = %x\n",
++				 mt76_rr(dev, EBF_BBP_RX_OFFSET));
++
++			td->tx_antenna_mask = 1;
++		}
++		width = phy->mt76->chandef.width;
++
++		if (td->tx_rate_mode == MT76_TM_TX_MODE_EHT_MU)
++			td->tx_rate_mode = MT76_TM_TX_MODE_EHT_SU;
++	}
++	mt76_testmode_param_set(td, MT76_TM_ATTR_TX_ANTENNA);
++
++	mt7996_tm_set(dev, SET_ID(TX_MODE),
++		      mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY));
++	mt7996_tm_set(dev, SET_ID(TX_RATE), td->tx_rate_idx);
++	mt7996_tm_set(dev, SET_ID(GI), td->tx_rate_sgi);
++	mt7996_tm_set(dev, SET_ID(CBW),
++		      mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_FW));
++	mt7996_tm_set(dev, SET_ID(DBW),
++		      mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_FW));
++	mt7996_tm_set_antenna(phy, SET_ID(TX_PATH));
++	mt7996_tm_set_antenna(phy, SET_ID(RX_PATH));
++	mt7996_tm_set(dev, SET_ID(IPG), td->tx_ipg);
++	mt7996_tm_set(dev, SET_ID(TX_LEN), td->tx_mpdu_len);
++	mt7996_tm_set(dev, SET_ID(TX_TIME), 0);
++	mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(TX_COMMIT));
++
++	return 0;
++}
++
++static int
++mt7996_tm_txbf_phase_comp(struct mt7996_phy *phy, u16 *val)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_bf_req req = {
++		.phase_comp = {
++			.tag = cpu_to_le16(BF_IBF_PHASE_COMP),
++			.len = cpu_to_le16(sizeof(req.phase_comp)),
++			.bw = val[0],
++			.jp_band = (val[2] == 1) ? 1 : 0,
++			.band_idx = phy->mt76->band_idx,
++			.read_from_e2p = val[3],
++			.disable = val[4],
++			.group = val[2],
++		}
++	};
++	struct mt7996_txbf_phase *phase = (struct mt7996_txbf_phase *)dev->test.txbf_phase_cal;
++
++	wait_event_timeout(dev->mt76.tx_wait, phase[val[2]].status != 0, HZ);
++	if (val[2])
++		memcpy(req.phase_comp.buf, &phase[val[2]].phase_5g, sizeof(req.phase_comp.buf));
++	else
++		memcpy(req.phase_comp.buf, &phase[val[2]].phase_2g, sizeof(req.phase_comp.buf));
++
++	pr_info("ibf cal process: phase comp info\n");
++	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
++		       &req, sizeof(req), 0);
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &req,
++				 sizeof(req), false);
++}
++
++static int
++mt7996_tm_txbf_profile_tag_write(struct mt7996_phy *phy, u8 pfmu_idx, struct mt7996_pfmu_tag *tag)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_bf_req req = {
++		.pfmu_tag = {
++			.tag = cpu_to_le16(BF_PFMU_TAG_WRITE),
++			.len = cpu_to_le16(sizeof(req.pfmu_tag)),
++			.pfmu_id = pfmu_idx,
++			.bfer = true,
++			.band_idx = phy->mt76->band_idx,
++		}
++	};
++
++	memcpy(req.pfmu_tag.buf, tag, sizeof(*tag));
++	wait_event_timeout(dev->mt76.tx_wait, tag->t1.pfmu_idx != 0, HZ);
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &req,
++				 sizeof(req), false);
++}
++
++static int
++mt7996_tm_add_txbf_sta(struct mt7996_phy *phy, u8 pfmu_idx, u8 nr, u8 nc, bool ebf)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct {
++		struct sta_req_hdr hdr;
++		struct sta_rec_bf bf;
++	} __packed req = {
++		.hdr = {
++			.bss_idx = phy->mt76->band_idx,
++			.wlan_idx_lo = to_wcid_lo(phy->mt76->band_idx + 1),
++			.tlv_num = 1,
++			.is_tlv_append = 1,
++			.muar_idx = 0,
++			.wlan_idx_hi = to_wcid_hi(phy->mt76->band_idx + 1),
++		},
++		.bf = {
++			.tag = cpu_to_le16(STA_REC_BF),
++			.len = cpu_to_le16(sizeof(req.bf)),
++			.pfmu = cpu_to_le16(pfmu_idx),
++			.sounding_phy = 1,
++			.bf_cap = ebf,
++			.ncol = nc,
++			.nrow = nr,
++			.ibf_timeout = 0xff,
++			.tx_mode = mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY),
++		},
++	};
++	u8 ndp_rate, ndpa_rate, rept_poll_rate, bf_bw;
++
++	if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_SU ||
++	    td->tx_rate_mode == MT76_TM_TX_MODE_EHT_SU) {
++		rept_poll_rate = 0x49;
++		ndpa_rate = 0x49;
++		ndp_rate = 0;
++	} else if (td->tx_rate_mode == MT76_TM_TX_MODE_VHT) {
++		rept_poll_rate = 0x9;
++		ndpa_rate = 0x9;
++		ndp_rate = 0;
++	} else {
++		rept_poll_rate = 0;
++		ndpa_rate = 0;
++		if (nr == 1)
++			ndp_rate = 8;
++		else if (nr == 2)
++			ndp_rate = 16;
++		else
++			ndp_rate = 24;
++	}
++
++	bf_bw = mt7996_tm_bw_mapping(phy->mt76->chandef.width, BW_MAP_NL_TO_BF);
++	req.bf.ndp_rate = ndp_rate;
++	req.bf.ndpa_rate = ndpa_rate;
++	req.bf.rept_poll_rate = rept_poll_rate;
++	req.bf.bw = bf_bw;
++	req.bf.tx_mode = (td->tx_rate_mode == MT76_TM_TX_MODE_EHT_SU) ? 0xf : req.bf.tx_mode;
++
++	if (ebf) {
++		req.bf.mem[0].row = 0;
++		req.bf.mem[1].row = 1;
++		req.bf.mem[2].row = 2;
++		req.bf.mem[3].row = 3;
++	} else {
++		req.bf.mem[0].row = 4;
++		req.bf.mem[1].row = 5;
++		req.bf.mem[2].row = 6;
++		req.bf.mem[3].row = 7;
++	}
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), &req,
++				 sizeof(req), true);
++}
++
++static int
++mt7996_tm_txbf_profile_update(struct mt7996_phy *phy, u16 *val, bool ebf)
++{
++#define MT_ARB_IBF_ENABLE			(BIT(0) | GENMASK(9, 8))
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_pfmu_tag *tag = dev->test.txbf_pfmu_tag;
++	u8 pfmu_idx = val[0], nc = val[2], nr;
++	int ret;
++	bool is_atenl = val[5];
++
++	if (td->tx_antenna_mask == 3)
++		nr = 1;
++	else if (td->tx_antenna_mask == 7)
++		nr = 2;
++	else
++		nr = 3;
++
++	memset(tag, 0, sizeof(*tag));
++	tag->t1.pfmu_idx = pfmu_idx;
++	tag->t1.ebf = ebf;
++	tag->t1.nr = nr;
++	tag->t1.nc = nc;
++	tag->t1.invalid_prof = true;
++	tag->t1.data_bw = mt7996_tm_bw_mapping(phy->mt76->chandef.width, BW_MAP_NL_TO_BF);
++	tag->t2.se_idx = td->tx_spe_idx;
++
++	if (ebf) {
++		tag->t1.row_id1 = 0;
++		tag->t1.row_id2 = 1;
++		tag->t1.row_id3 = 2;
++		tag->t1.row_id4 = 3;
++		tag->t1.lm = mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_LM);
++	} else {
++		tag->t1.row_id1 = 4;
++		tag->t1.row_id2 = 5;
++		tag->t1.row_id3 = 6;
++		tag->t1.row_id4 = 7;
++		tag->t1.lm = mt7996_tm_rate_mapping(MT76_TM_TX_MODE_OFDM, RATE_MODE_TO_LM);
++
++		tag->t2.ibf_timeout = 0xff;
++		tag->t2.ibf_nr = nr;
++		tag->t2.ibf_nc = nc;
++	}
++
++	ret = mt7996_tm_txbf_profile_tag_write(phy, pfmu_idx, tag);
++	if (ret)
++		return ret;
++
++	ret = mt7996_tm_add_txbf_sta(phy, pfmu_idx, nr, nc, ebf);
++	if (ret)
++		return ret;
++
++	if (!is_atenl && !td->ibf) {
++		mt76_set(dev, MT_ARB_TQSAXM0(phy->mt76->band_idx), MT_ARB_TQSAXM_ALTX_START_MASK);
++		dev_info(dev->mt76.dev, "Set TX queue start CR for AX management (0x%x) = 0x%x\n",
++			 MT_ARB_TQSAXM0(phy->mt76->band_idx),
++			 mt76_rr(dev, MT_ARB_TQSAXM0(phy->mt76->band_idx)));
++	} else if (!is_atenl && td->ibf && ebf) {
++		/* iBF's ebf profile update */
++		mt76_set(dev, MT_ARB_TQSAXM0(phy->mt76->band_idx), MT_ARB_IBF_ENABLE);
++		dev_info(dev->mt76.dev, "Set TX queue start CR for AX management (0x%x) = 0x%x\n",
++			 MT_ARB_TQSAXM0(phy->mt76->band_idx),
++			 mt76_rr(dev, MT_ARB_TQSAXM0(phy->mt76->band_idx)));
++	}
++
++	if (!ebf && is_atenl)
++		return mt7996_tm_txbf_apply_tx(phy, 1, false, true, true);
++
++	return 0;
++}
++
++static int
++mt7996_tm_txbf_phase_cal(struct mt7996_phy *phy, u16 *val)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_bf_req req = {
++		.phase_cal = {
++			.tag = cpu_to_le16(BF_PHASE_CALIBRATION),
++			.len = cpu_to_le16(sizeof(req.phase_cal)),
++			.group = val[0],
++			.group_l_m_n = val[1],
++			.sx2 = val[2],
++			.cal_type = val[3],
++			.lna_gain_level = val[4],
++			.band_idx = phy->mt76->band_idx,
++		},
++	};
++	struct mt7996_txbf_phase *phase = (struct mt7996_txbf_phase *)dev->test.txbf_phase_cal;
++
++	/* reset phase status before update phase cal data */
++	phase[req.phase_cal.group].status = 0;
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &req,
++				 sizeof(req), false);
++}
++
++static int
++mt7996_tm_txbf_profile_update_all(struct mt7996_phy *phy, u16 *val)
++{
++#define MT7996_TXBF_PFMU_DATA_LEN	(MT7996_TXBF_SUBCAR_NUM * sizeof(struct mt7996_pfmu_data))
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	u8 nss = hweight8(td->tx_antenna_mask);
++	u16 pfmu_idx = val[0];
++	u16 subc_id = val[1];
++	u16 angle11 = val[2];
++	u16 angle21 = val[3];
++	u16 angle31 = val[4];
++	u16 angle41 = val[5];
++	s16 phi11 = 0, phi21 = 0, phi31 = 0;
++	struct mt7996_pfmu_data *pfmu_data;
++
++	if (subc_id > MT7996_TXBF_SUBCAR_NUM - 1)
++		return -EINVAL;
++
++	if (nss == 2) {
++		phi11 = (s16)(angle21 - angle11);
++	} else if (nss == 3) {
++		phi11 = (s16)(angle31 - angle11);
++		phi21 = (s16)(angle31 - angle21);
++	} else {
++		phi11 = (s16)(angle41 - angle11);
++		phi21 = (s16)(angle41 - angle21);
++		phi31 = (s16)(angle41 - angle31);
++	}
++
++	pfmu_data = (struct mt7996_pfmu_data *)phy->dev->test.txbf_pfmu_data;
++	pfmu_data = &pfmu_data[subc_id];
++
++	if (subc_id < 32)
++		pfmu_data->subc_idx = cpu_to_le16(subc_id + 224);
++	else
++		pfmu_data->subc_idx = cpu_to_le16(subc_id - 32);
++
++	pfmu_data->phi11 = cpu_to_le16(phi11);
++	pfmu_data->phi21 = cpu_to_le16(phi21);
++	pfmu_data->phi31 = cpu_to_le16(phi31);
++	if (subc_id == MT7996_TXBF_SUBCAR_NUM - 1) {
++		struct mt7996_dev *dev = phy->dev;
++		struct mt7996_tm_bf_req req = {
++			.pfmu_data_all = {
++				.tag = cpu_to_le16(BF_PROFILE_WRITE_20M_ALL),
++				.len = cpu_to_le16(sizeof(req.pfmu_data_all)),
++				.pfmu_id = pfmu_idx,
++				.band_idx = phy->mt76->band_idx,
++			},
++		};
++
++		memcpy(req.pfmu_data_all.buf, dev->test.txbf_pfmu_data, MT7996_TXBF_PFMU_DATA_LEN);
++
++		return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF),
++					 &req, sizeof(req), true);
++	}
++
++	return 0;
++}
++
++static int
++mt7996_tm_txbf_e2p_update(struct mt7996_phy *phy)
++{
++#define TXBF_PHASE_EEPROM_START_OFFSET		0xc00
++#define TXBF_PHASE_GROUP_EEPROM_OFFSET		0x2e
++	struct mt7996_txbf_phase *phase, *p;
++	struct mt7996_dev *dev = phy->dev;
++	u8 *eeprom = dev->mt76.eeprom.data;
++	u16 offset;
++	int i;
++
++	offset = TXBF_PHASE_EEPROM_START_OFFSET;
++	phase = (struct mt7996_txbf_phase *)dev->test.txbf_phase_cal;
++	for (i = 0; i < MAX_PHASE_GROUP_NUM; i++) {
++		p = &phase[i];
++
++		if (!p->status)
++			continue;
++
++		/* copy phase cal data to eeprom */
++		if (i)
++			memcpy(eeprom + offset, &p->phase_5g, sizeof(p->phase_5g));
++		else
++			memcpy(eeprom + offset, &p->phase_2g, sizeof(p->phase_2g));
++		offset += TXBF_PHASE_GROUP_EEPROM_OFFSET;
++	}
++
++	return 0;
++}
++
++static int
++mt7996_tm_txbf_apply_tx(struct mt7996_phy *phy, u16 wlan_idx, bool ebf,
++			bool ibf, bool phase_cal)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_bf_req req = {
++		.tx_apply = {
++			.tag = cpu_to_le16(BF_DATA_PACKET_APPLY),
++			.len = cpu_to_le16(sizeof(req.tx_apply)),
++			.wlan_idx = cpu_to_le16(wlan_idx),
++			.ebf = ebf,
++			.ibf = ibf,
++			.phase_cal = phase_cal,
++		},
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &req, sizeof(req), false);
++}
++
++static int
++mt7996_tm_txbf_set_tx(struct mt7996_phy *phy, u16 *val)
++{
++	bool bf_on = val[0], update = val[3];
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_pfmu_tag *tag = dev->test.txbf_pfmu_tag;
++	struct mt76_testmode_data *td = &phy->mt76->test;
++
++	if (bf_on) {
++		mt7996_tm_set_rx_frames(phy, false);
++		mt7996_tm_set_tx_frames(phy, false);
++		mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, 2, true);
++		tag->t1.invalid_prof = false;
++		mt7996_tm_txbf_profile_tag_write(phy, 2, tag);
++		td->bf_ever_en = true;
++
++		if (update)
++			mt7996_tm_txbf_apply_tx(phy, 1, 0, 1, 1);
++	} else {
++		if (!td->bf_ever_en) {
++			mt7996_tm_set_rx_frames(phy, false);
++			mt7996_tm_set_tx_frames(phy, false);
++			td->ibf = false;
++			td->ebf = false;
++
++			if (update)
++				mt7996_tm_txbf_apply_tx(phy, 1, 0, 0, 0);
++		} else {
++			td->bf_ever_en = false;
++
++			mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, 2, true);
++			tag->t1.invalid_prof = true;
++			mt7996_tm_txbf_profile_tag_write(phy, 2, tag);
++		}
++	}
++
++	return 0;
++}
++
++static int
++mt7996_tm_trigger_sounding(struct mt7996_phy *phy, u16 *val, bool en)
++{
++	struct mt7996_dev *dev = phy->dev;
++	u8 sounding_mode = val[0];
++	u8 sta_num = val[1];
++	u32 sounding_interval = (u32)val[2] << 2;	/* input unit: 4ms */
++	u16 tag = en ? BF_SOUNDING_ON : BF_SOUNDING_OFF;
++	struct mt7996_tm_bf_req req = {
++		.sounding = {
++			.tag = cpu_to_le16(tag),
++			.len = cpu_to_le16(sizeof(req.sounding)),
++			.snd_mode = sounding_mode,
++			.sta_num = sta_num,
++			.wlan_id = {
++				cpu_to_le16(val[3]),
++				cpu_to_le16(val[4]),
++				cpu_to_le16(val[5]),
++				cpu_to_le16(val[6])
++			},
++			.snd_period = cpu_to_le32(sounding_interval),
++		},
++	};
++
++	if (sounding_mode > SOUNDING_MODE_MAX)
++		return -EINVAL;
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF),
++				 &req, sizeof(req), false);
++}
++
++static int
++mt7996_tm_txbf_txcmd(struct mt7996_phy *phy, u16 *val)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt7996_tm_bf_req req = {
++		.txcmd = {
++			.tag = cpu_to_le16(BF_CMD_TXCMD),
++			.len = cpu_to_le16(sizeof(req.txcmd)),
++			.action = val[0],
++			.bf_manual = val[1],
++			.bf_bit = val[2],
++		},
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(BF), &req, sizeof(req), false);
++}
++
++static int
++mt7996_tm_set_txbf(struct mt7996_phy *phy)
++{
++#define TXBF_IS_DUT_MASK	BIT(0)
++#define TXBF_IBF_MASK		BIT(1)
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	u16 *val = td->txbf_param;
++
++	dev_info(phy->dev->mt76.dev,
++		 "ibf cal process: act = %u, val = %u, %u, %u, %u, %u, %u, %u, %u\n",
++		 td->txbf_act, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
++
++	switch (td->txbf_act) {
++	case MT76_TM_TXBF_ACT_GOLDEN_INIT:
++	case MT76_TM_TXBF_ACT_INIT:
++	case MT76_TM_TX_EBF_ACT_GOLDEN_INIT:
++	case MT76_TM_TX_EBF_ACT_INIT:
++		td->ibf = !u32_get_bits(td->txbf_act, TXBF_IBF_MASK);
++		td->ebf = true;
++		td->is_txbf_dut = !!u32_get_bits(td->txbf_act, TXBF_IS_DUT_MASK);
++		return mt7996_tm_txbf_init(phy, val);
++	case MT76_TM_TXBF_ACT_UPDATE_CH:
++		mt7996_tm_update_channel(phy);
++		break;
++	case MT76_TM_TXBF_ACT_PHASE_COMP:
++		return mt7996_tm_txbf_phase_comp(phy, val);
++	case MT76_TM_TXBF_ACT_TX_PREP:
++		return mt7996_tm_txbf_set_tx(phy, val);
++	case MT76_TM_TXBF_ACT_IBF_PROF_UPDATE:
++		return mt7996_tm_txbf_profile_update(phy, val, false);
++	case MT76_TM_TXBF_ACT_EBF_PROF_UPDATE:
++		return mt7996_tm_txbf_profile_update(phy, val, true);
++	case MT76_TM_TXBF_ACT_PHASE_CAL:
++		return mt7996_tm_txbf_phase_cal(phy, val);
++	case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD:
++	case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL:
++		return mt7996_tm_txbf_profile_update_all(phy, val);
++	case MT76_TM_TXBF_ACT_E2P_UPDATE:
++		return mt7996_tm_txbf_e2p_update(phy);
++	case MT76_TM_TXBF_ACT_APPLY_TX: {
++		u16 wlan_idx = val[0];
++		bool ebf = !!val[1], ibf = !!val[2], phase_cal = !!val[4];
++
++		return mt7996_tm_txbf_apply_tx(phy, wlan_idx, ebf, ibf, phase_cal);
++	}
++	case MT76_TM_TXBF_ACT_TRIGGER_SOUNDING:
++		return mt7996_tm_trigger_sounding(phy, val, true);
++	case MT76_TM_TXBF_ACT_STOP_SOUNDING:
++		memset(val, 0, sizeof(td->txbf_param));
++		return mt7996_tm_trigger_sounding(phy, val, false);
++	case MT76_TM_TXBF_ACT_PROFILE_TAG_READ:
++	case MT76_TM_TXBF_ACT_PROFILE_TAG_WRITE:
++	case MT76_TM_TXBF_ACT_PROFILE_TAG_INVALID: {
++		u8 pfmu_idx = val[0];
++		bool bfer = !!val[1];
++		struct mt7996_dev *dev = phy->dev;
++		struct mt7996_pfmu_tag *tag = dev->test.txbf_pfmu_tag;
++
++		if (!tag) {
++			dev_err(dev->mt76.dev,
++				"pfmu tag is not initialized!\n");
++			return 0;
++		}
++
++		if (td->txbf_act == MT76_TM_TXBF_ACT_PROFILE_TAG_WRITE)
++			return mt7996_tm_txbf_profile_tag_write(phy, pfmu_idx, tag);
++		else if (td->txbf_act == MT76_TM_TXBF_ACT_PROFILE_TAG_READ)
++			return mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, pfmu_idx, bfer);
++
++		tag->t1.invalid_prof = !!val[0];
++
++		return 0;
++	}
++	case MT76_TM_TXBF_ACT_STA_REC_READ:
++		return mt7996_mcu_set_txbf_internal(phy, BF_STA_REC_READ, val[0], 0);
++	case MT76_TM_TXBF_ACT_TXCMD:
++		return mt7996_tm_txbf_txcmd(phy, val);
++	default:
++		break;
++	};
++
++	return 0;
++}
++
+ static void
+ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+ {
+@@ -1086,6 +1770,8 @@ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+ 		mt7996_tm_set_ipi(phy);
+ 	if (changed & BIT(TM_CHANGED_IPI_RESET))
+ 		mt7996_tm_ipi_hist_ctrl(phy, NULL, RDD_SET_IPI_HIST_RESET);
++	if (changed & BIT(TM_CHANGED_TXBF_ACT))
++		mt7996_tm_set_txbf(phy);
+ }
+ 
+ static int
+diff --git a/mt7996/testmode.h b/mt7996/testmode.h
+index 78662b2e..f97ccb26 100644
+--- a/mt7996/testmode.h
++++ b/mt7996/testmode.h
+@@ -27,6 +27,17 @@ enum {
+ 	FW_CDBW_8080MHZ,
+ };
+ 
++enum {
++	BF_CDBW_20MHZ,
++	BF_CDBW_40MHZ,
++	BF_CDBW_80MHZ,
++	BF_CDBW_160MHZ,
++	BF_CDBW_320MHZ,
++	BF_CDBW_10MHZ = BF_CDBW_320MHZ,
++	BF_CDBW_5MHZ,
++	BF_CDBW_8080MHZ,
++};
++
+ #define FIRST_CONTROL_CHAN_BITMAP_BW40		0x5555555
+ #define FIRST_CONTROL_CHAN_BITMAP_BW80		0x111111
+ #define FIRST_CONTROL_CHAN_BITMAP_BW160		0x100101
+@@ -34,12 +45,20 @@ enum {
+ enum bw_mapping_method {
+ 	BW_MAP_NL_TO_FW,
+ 	BW_MAP_NL_TO_TM,
++	BW_MAP_NL_TO_BF,
+ 	BW_MAP_NL_TO_MHZ,
+ 	BW_MAP_NL_TO_CONTROL_BITMAP_5G,
+ 
+ 	NUM_BW_MAP,
+ };
+ 
++enum rate_mapping_type {
++	RATE_MODE_TO_PHY,
++	RATE_MODE_TO_LM,
++
++	NUM_RATE_MAP,
++};
++
+ struct tm_cal_param {
+ 	__le32 func_data;
+ 	u8 band_idx;
+diff --git a/testmode.c b/testmode.c
+index 805ad83c..7b8f9e66 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -462,6 +462,42 @@ out:
+ 	return err;
+ }
+ 
++static int
++mt76_testmode_txbf_profile_update_all_cmd(struct mt76_phy *phy, struct nlattr **tb, u32 state)
++{
++#define PARAM_UNIT	5
++	static u8 pfmu_idx;
++	struct mt76_testmode_data *td = &phy->test;
++	struct mt76_dev *dev = phy->dev;
++	struct nlattr *cur;
++	u16 tmp_val[PARAM_UNIT], *val = td->txbf_param;
++	int idx, rem, ret, i = 0;
++
++	memset(td->txbf_param, 0, sizeof(td->txbf_param));
++	nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
++		if (nla_len(cur) != 2)
++			return -EINVAL;
++		idx = i % PARAM_UNIT;
++		tmp_val[idx] = nla_get_u16(cur);
++		if (idx == 1 && (tmp_val[idx] == 0xf0 || tmp_val[idx] == 0xff)) {
++			pfmu_idx = tmp_val[0];
++			return 0;
++		}
++		if (idx == PARAM_UNIT - 1) {
++			val[0] = pfmu_idx;
++			memcpy(val + 1, tmp_val, sizeof(tmp_val));
++			if (dev->test_ops->set_params) {
++				ret = dev->test_ops->set_params(phy, tb, state);
++				if (ret)
++					return ret;
++			}
++		}
++		i++;
++	}
++
++	return 0;
++}
++
+ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		      void *data, int len)
+ {
+@@ -607,6 +643,30 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		}
+ 	}
+ 
++	if (tb[MT76_TM_ATTR_TXBF_ACT]) {
++		struct nlattr *cur;
++		int rem, idx = 0;
++
++		if (!tb[MT76_TM_ATTR_TXBF_PARAM] ||
++		    mt76_tm_get_u8(tb[MT76_TM_ATTR_TXBF_ACT], &td->txbf_act,
++				   0, MT76_TM_TXBF_ACT_MAX))
++			goto out;
++
++		if (td->txbf_act == MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD) {
++			err = mt76_testmode_txbf_profile_update_all_cmd(phy, tb, state);
++			goto out;
++		}
++
++		memset(td->txbf_param, 0, sizeof(td->txbf_param));
++		nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
++			if (nla_len(cur) != 2 ||
++			    idx >= ARRAY_SIZE(td->txbf_param))
++				goto out;
++
++			td->txbf_param[idx++] = nla_get_u16(cur);
++		}
++	}
++
+ 	if (dev->test_ops->set_params) {
+ 		err = dev->test_ops->set_params(phy, tb, state);
+ 		if (err)
+diff --git a/testmode.h b/testmode.h
+index 5d677f8c..bda7624a 100644
+--- a/testmode.h
++++ b/testmode.h
+@@ -286,6 +286,59 @@ enum mt76_testmode_eeprom_action {
+ 	MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
+ };
+ 
++/**
++ * enum mt76_testmode_txbf_act - txbf action
++ *
++ * @MT76_TM_TXBF_ACT_GOLDEN_INIT: init ibf setting for golden device
++ * @MT76_TM_TXBF_ACT_INIT: init ibf setting for DUT
++ * @MT76_TM_TX_EBF_ACT_GOLDEN_INIT: init ebf setting for golden device
++ * @MT76_TM_TX_EBF_ACT_INIT: init ebf setting for DUT
++ * @MT76_TM_TXBF_ACT_UPDATE_CH: update channel info
++ * @MT76_TM_TXBF_ACT_PHASE_COMP: txbf phase compensation
++ * @MT76_TM_TXBF_ACT_TX_PREP: TX preparation for txbf
++ * @MT76_TM_TXBF_ACT_IBF_PROF_UPDATE: update ibf profile (pfmu tag, bf sta record)
++ * @MT76_TM_TXBF_ACT_EBF_PROF_UPDATE: update ebf profile
++ * @MT76_TM_TXBF_ACT_APPLY_TX: apply TX setting for txbf
++ * @MT76_TM_TXBF_ACT_PHASE_CAL: perform txbf phase calibration
++ * @MT76_TM_TXBF_ACT_PROF_UPDATE_ALL: update bf profile via instrument
++ * @MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD: update bf profile via instrument
++ * @MT76_TM_TXBF_ACT_E2P_UPDATE: write back txbf calibration result to eeprom
++ * @MT76_TM_TXBF_ACT_TRIGGER_SOUNDING: trigger beamformer to send sounding packet
++ * @MT76_TM_TXBF_ACT_STOP_SOUNDING: stop sending sounding packet
++ * @MT76_TM_TXBF_ACT_PROFILE_TAG_READ: read pfmu tag
++ * @MT76_TM_TXBF_ACT_PROFILE_TAG_WRITE: update pfmu tag
++ * @MT76_TM_TXBF_ACT_PROFILE_TAG_INVALID: invalidate pfmu tag
++ * @MT76_TM_TXBF_ACT_STA_REC_READ: read bf sta record
++ * @MT76_TM_TXBF_ACT_TXCMD: configure txcmd bf bit manually
++ */
++enum mt76_testmode_txbf_act {
++	MT76_TM_TXBF_ACT_GOLDEN_INIT,
++	MT76_TM_TXBF_ACT_INIT,
++	MT76_TM_TX_EBF_ACT_GOLDEN_INIT,
++	MT76_TM_TX_EBF_ACT_INIT,
++	MT76_TM_TXBF_ACT_UPDATE_CH,
++	MT76_TM_TXBF_ACT_PHASE_COMP,
++	MT76_TM_TXBF_ACT_TX_PREP,
++	MT76_TM_TXBF_ACT_IBF_PROF_UPDATE,
++	MT76_TM_TXBF_ACT_EBF_PROF_UPDATE,
++	MT76_TM_TXBF_ACT_APPLY_TX,
++	MT76_TM_TXBF_ACT_PHASE_CAL,
++	MT76_TM_TXBF_ACT_PROF_UPDATE_ALL,
++	MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD,
++	MT76_TM_TXBF_ACT_E2P_UPDATE,
++	MT76_TM_TXBF_ACT_TRIGGER_SOUNDING,
++	MT76_TM_TXBF_ACT_STOP_SOUNDING,
++	MT76_TM_TXBF_ACT_PROFILE_TAG_READ,
++	MT76_TM_TXBF_ACT_PROFILE_TAG_WRITE,
++	MT76_TM_TXBF_ACT_PROFILE_TAG_INVALID,
++	MT76_TM_TXBF_ACT_STA_REC_READ,
++	MT76_TM_TXBF_ACT_TXCMD,
++
++	/* keep last */
++	NUM_MT76_TM_TXBF_ACT,
++	MT76_TM_TXBF_ACT_MAX = NUM_MT76_TM_TXBF_ACT - 1,
++};
++
+ extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
+ 
+ #endif
+diff --git a/tools/fields.c b/tools/fields.c
+index 77696ce7..f793d1a5 100644
+--- a/tools/fields.c
++++ b/tools/fields.c
+@@ -44,6 +44,30 @@ static const char * const testmode_offchan_bw[] = {
+ 	[NL80211_CHAN_WIDTH_160] = "160",
+ };
+ 
++static const char * const testmode_txbf_act[] = {
++	[MT76_TM_TXBF_ACT_GOLDEN_INIT] = "golden_init",
++	[MT76_TM_TXBF_ACT_INIT] = "init",
++	[MT76_TM_TX_EBF_ACT_GOLDEN_INIT] = "ebf_golden_init",
++	[MT76_TM_TX_EBF_ACT_INIT] = "ebf_init",
++	[MT76_TM_TXBF_ACT_UPDATE_CH] = "update_ch",
++	[MT76_TM_TXBF_ACT_PHASE_COMP] = "phase_comp",
++	[MT76_TM_TXBF_ACT_TX_PREP] = "tx_prep",
++	[MT76_TM_TXBF_ACT_IBF_PROF_UPDATE] = "ibf_prof_update",
++	[MT76_TM_TXBF_ACT_EBF_PROF_UPDATE] = "ebf_prof_update",
++	[MT76_TM_TXBF_ACT_APPLY_TX] = "apply_tx",
++	[MT76_TM_TXBF_ACT_PHASE_CAL] = "phase_cal",
++	[MT76_TM_TXBF_ACT_PROF_UPDATE_ALL] = "prof_update",
++	[MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD] = "prof_update_all",
++	[MT76_TM_TXBF_ACT_E2P_UPDATE] = "e2p_update",
++	[MT76_TM_TXBF_ACT_TRIGGER_SOUNDING] = "trigger_sounding",
++	[MT76_TM_TXBF_ACT_STOP_SOUNDING] = "stop_sounding",
++	[MT76_TM_TXBF_ACT_PROFILE_TAG_READ] = "pfmu_tag_read",
++	[MT76_TM_TXBF_ACT_PROFILE_TAG_WRITE] = "pfmu_tag_write",
++	[MT76_TM_TXBF_ACT_PROFILE_TAG_INVALID] = "set_invalid_prof",
++	[MT76_TM_TXBF_ACT_STA_REC_READ] = "sta_rec_read",
++	[MT76_TM_TXBF_ACT_TXCMD] = "txcmd",
++};
++
+ static void print_enum(const struct tm_field *field, struct nlattr *attr)
+ {
+ 	unsigned int i = nla_get_u8(attr);
+@@ -94,6 +118,17 @@ static void print_s8(const struct tm_field *field, struct nlattr *attr)
+ 	printf("%d", (int8_t)nla_get_u8(attr));
+ }
+ 
++static bool parse_u16_hex(const struct tm_field *field, int idx,
++			  struct nl_msg *msg, const char *val)
++{
++	return !nla_put_u16(msg, idx, strtoul(val, NULL, 16));
++}
++
++static void print_u16_hex(const struct tm_field *field, struct nlattr *attr)
++{
++	printf("%d", nla_get_u16(attr));
++}
++
+ static bool parse_u32(const struct tm_field *field, int idx,
+ 		      struct nl_msg *msg, const char *val)
+ {
+@@ -399,6 +434,8 @@ 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"),
++	FIELD_ENUM(TXBF_ACT, "txbf_act", testmode_txbf_act),
++	FIELD_ARRAY(u16_hex, TXBF_PARAM, "txbf_param"),
+ 	FIELD(u8, OFF_CH_SCAN_CH, "offchan_ch"),
+ 	FIELD(u8, OFF_CH_SCAN_CENTER_CH, "offchan_center_ch"),
+ 	FIELD_ENUM(OFF_CH_SCAN_BW, "offchan_bw", testmode_offchan_bw),
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1034-mtk-wifi-mt76-mt7996-add-zwdfs-cert-mode.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1034-mtk-wifi-mt76-mt7996-add-zwdfs-cert-mode.patch
new file mode 100644
index 0000000..45a2131
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1034-mtk-wifi-mt76-mt7996-add-zwdfs-cert-mode.patch
@@ -0,0 +1,221 @@
+From b7bac1d2e4c144961ffd4b96a7fe9c5ea56bb1f3 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 22 Sep 2023 12:33:06 +0800
+Subject: [PATCH 1034/1041] mtk: wifi: mt76: mt7996: add zwdfs cert mode
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mcu.c    | 44 ++++++++++++++++++++++++++++++++------------
+ mt7996/mcu.h    | 14 ++++++++++++++
+ mt7996/mt7996.h |  5 +++++
+ mt7996/vendor.c | 37 +++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 12 ++++++++++++
+ 5 files changed, 100 insertions(+), 12 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6ba9c9d5..55e8cb1e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4501,18 +4501,7 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable)
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 		       u8 rx_sel, u8 val)
+ {
+-	struct {
+-		u8 _rsv[4];
+-
+-		__le16 tag;
+-		__le16 len;
+-
+-		u8 ctrl;
+-		u8 rdd_idx;
+-		u8 rdd_rx_sel;
+-		u8 val;
+-		u8 rsv[4];
+-	} __packed req = {
++	struct mt7996_rdd_ctrl req = {
+ 		.tag = cpu_to_le16(UNI_RDD_CTRL_PARM),
+ 		.len = cpu_to_le16(sizeof(req) - 4),
+ 		.ctrl = cmd,
+@@ -4525,6 +4514,37 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 				 &req, sizeof(req), true);
+ }
+ 
++int mt7996_mcu_rdd_background_disable_timer(struct mt7996_dev *dev, bool disable_timer)
++{
++	struct mt7996_rdd_ctrl req = {
++		.tag = cpu_to_le16(UNI_RDD_CTRL_PARM),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.ctrl = RDD_DISABLE_ZW_TIMER,
++		.rdd_idx = MT_RX_SEL2,
++		.disable_timer = disable_timer,
++	};
++
++	if (!is_mt7996(&dev->mt76) ||
++	    (mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) % 2))
++		return 0;
++
++	switch (dev->mt76.region) {
++	case NL80211_DFS_ETSI:
++		req.val = 0;
++		break;
++	case NL80211_DFS_JP:
++		req.val = 2;
++		break;
++	case NL80211_DFS_FCC:
++	default:
++		req.val = 1;
++		break;
++	}
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RDD_CTRL),
++				 &req, sizeof(req), true);
++}
++
+ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ 				     struct ieee80211_vif *vif,
+ 				     struct ieee80211_sta *sta)
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 054a616b..398bf3d2 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -119,6 +119,20 @@ struct mt7996_mcu_rdd_report {
+ 	} hw_pulse[32];
+ } __packed;
+ 
++struct mt7996_rdd_ctrl {
++	u8 _rsv[4];
++
++	__le16 tag;
++	__le16 len;
++
++	u8 ctrl;
++	u8 rdd_idx;
++	u8 rdd_rx_sel;
++	u8 val;
++	u8 disable_timer;
++	u8 rsv[3];
++} __packed;
++
+ struct mt7996_mcu_background_chain_ctrl {
+ 	u8 _rsv[4];
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index b5ce4a55..339d9890 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -516,8 +516,11 @@ enum mt7996_rdd_cmd {
+ 	RDD_READ_PULSE,
+ 	RDD_RESUME_BF,
+ 	RDD_IRQ_OFF,
++	RDD_DISABLE_ZW_TIMER,
+ };
+ 
++#define RDD_ZW_TIMER_OFF	BIT(31)
++
+ static inline struct mt7996_phy *
+ mt7996_hw_phy(struct ieee80211_hw *hw)
+ {
+@@ -659,6 +662,8 @@ int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
+ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 		       u8 rx_sel, u8 val);
++int mt7996_mcu_rdd_background_disable_timer(struct mt7996_dev *dev,
++					    bool disable_timer);
+ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
+ 				     struct cfg80211_chan_def *chandef);
+ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 477c5c42..c7fd3278 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -102,6 +102,11 @@ rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
+ 	[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 },
+ };
+ 
++static const struct nla_policy
++background_radar_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BACKGROUND_RADAR_CTRL] = {
++	[MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MODE] = {.type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ 	u8 idx;
+ 	u8 addr[ETH_ALEN];
+@@ -851,6 +856,27 @@ static int mt7996_vendor_wireless_ctrl(struct wiphy *wiphy,
+ 	return 0;
+ }
+ 
++static int mt7996_vendor_background_radar_mode_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_dev *dev = mt7996_hw_dev(hw);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_BACKGROUND_RADAR_CTRL];
++	int err;
++	u8 background_radar_mode;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MAX, data, data_len,
++			background_radar_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	background_radar_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MODE]);
++
++	return mt7996_mcu_rdd_background_disable_timer(dev, !!background_radar_mode);
++}
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -945,6 +971,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = rfeature_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_BACKGROUND_RADAR_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_background_radar_mode_ctrl,
++		.policy = background_radar_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 7011914b..920b6e6a 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -14,6 +14,7 @@ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ 	MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
+ 	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
++	MTK_NL80211_VENDOR_SUBCMD_BACKGROUND_RADAR_CTRL = 0xcb,
+ };
+ 
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -126,6 +127,17 @@ enum mtk_vendor_attr_wireless_dump {
+ 		NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
+ };
+ 
++enum mtk_vendor_attr_background_radar_ctrl {
++	MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MODE,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_BACKGROUND_RADAR_CTRL,
++	MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_BACKGROUND_RADAR_CTRL - 1
++};
++
+ enum bw_sig {
+ 	BW_SIGNALING_DISABLE,
+ 	BW_SIGNALING_STATIC,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1035-mtk-wifi-mt76-testmode-add-channel-68-96.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1035-mtk-wifi-mt76-testmode-add-channel-68-96.patch
new file mode 100644
index 0000000..ada50df
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1035-mtk-wifi-mt76-testmode-add-channel-68-96.patch
@@ -0,0 +1,248 @@
+From 1df8b15784e507963fa58fd3ebd81af2f3953f7d Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 11 Sep 2023 14:43:07 +0800
+Subject: [PATCH 1035/1041] mtk: wifi: mt76: testmode: add channel 68 & 96
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Add all the channel between 68 & 96 since ibf 5g channel group 3 will use channel 84.
+Also, "mtk: wifi: mt76: testmode: add channel 68 & 96" can be
+merged into to "mtk: wifi: mt76: testmode: add basic testmode support"
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Fix 5g channel list size
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mac80211.c        |  9 +++++++++
+ mt7996/eeprom.c   | 49 +++++++++++++++++++++++++++++++++++++++++++++--
+ mt7996/eeprom.h   |  2 ++
+ mt7996/mcu.c      | 10 +++++++++-
+ mt7996/testmode.c | 15 ++++++++++++---
+ mt7996/testmode.h |  6 +++---
+ 6 files changed, 82 insertions(+), 9 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 45791f6e..f74f6e85 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -35,6 +35,15 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
+ 	CHAN5G(60, 5300),
+ 	CHAN5G(64, 5320),
+ 
++	CHAN5G(68, 5340),
++	CHAN5G(72, 5360),
++	CHAN5G(76, 5380),
++	CHAN5G(80, 5400),
++	CHAN5G(84, 5420),
++	CHAN5G(88, 5440),
++	CHAN5G(92, 5460),
++	CHAN5G(96, 5480),
++
+ 	CHAN5G(100, 5500),
+ 	CHAN5G(104, 5520),
+ 	CHAN5G(108, 5540),
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 372a822f..cff1b875 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -18,6 +18,17 @@ const struct ieee80211_channel dpd_2g_ch_list_bw20[] = {
+ 	CHAN2G(11, 2462)
+ };
+ 
++const struct ieee80211_channel dpd_5g_skip_ch_list[] = {
++	CHAN5G(68, 5340),
++	CHAN5G(72, 5360),
++	CHAN5G(76, 5380),
++	CHAN5G(80, 5400),
++	CHAN5G(84, 5420),
++	CHAN5G(88, 5440),
++	CHAN5G(92, 5460),
++	CHAN5G(96, 5480)
++};
++
+ const struct ieee80211_channel dpd_5g_ch_list_bw160[] = {
+ 	CHAN5G(50, 5250),
+ 	CHAN5G(114, 5570),
+@@ -44,6 +55,7 @@ const struct ieee80211_channel dpd_6g_ch_list_bw320[] = {
+ };
+ 
+ const u32 dpd_2g_bw20_ch_num = ARRAY_SIZE(dpd_2g_ch_list_bw20);
++const u32 dpd_5g_skip_ch_num = ARRAY_SIZE(dpd_5g_skip_ch_list);
+ const u32 dpd_5g_bw160_ch_num = ARRAY_SIZE(dpd_5g_ch_list_bw160);
+ const u32 dpd_6g_bw160_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw160);
+ const u32 dpd_6g_bw320_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw320);
+@@ -135,8 +147,8 @@ mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band)
+ 	if (band == NL80211_BAND_2GHZ)
+ 		dpd_size = dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
+ 	else if (band == NL80211_BAND_5GHZ)
+-		dpd_size = mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
+-			   dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++		dpd_size = (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
++			   DPD_PER_CH_BW20_SIZE + dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
+ 	else
+ 		dpd_size = mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
+ 			   (dpd_6g_bw160_ch_num + dpd_6g_bw320_ch_num) * DPD_PER_CH_GT_BW20_SIZE;
+@@ -396,6 +408,39 @@ out:
+ 	return ret;
+ }
+ 
++static void mt7996_eeprom_init_precal(struct mt7996_dev *dev)
++{
++#define MT76_CHANNELS_5GHZ_SIZE		36	/* ARRAY_SIZE(mt76_channels_5ghz) */
++#define MT76_CHANNELS_6GHZ_SIZE		59	/* ARRAY_SIZE(mt76_channels_6ghz) */
++
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW20_2G] = ARRAY_SIZE(dpd_2g_ch_list_bw20);
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW20_5G_SKIP] = ARRAY_SIZE(dpd_5g_skip_ch_list);
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW20_5G] = MT76_CHANNELS_5GHZ_SIZE -
++						   DPD_CH_NUM(BW20_5G_SKIP);
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW160_5G] = ARRAY_SIZE(dpd_5g_ch_list_bw160);
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW20_6G] = MT76_CHANNELS_6GHZ_SIZE;
++	dev->prek.dpd_ch_num[DPD_CH_NUM_BW160_6G] = ARRAY_SIZE(dpd_6g_ch_list_bw160);
++
++	switch (mt76_chip(&dev->mt76)) {
++	case 0x7990:
++		dev->prek.rev = mt7996_prek_rev;
++		/* 5g & 6g bw 80 dpd channel list is not used */
++		dev->prek.dpd_ch_num[DPD_CH_NUM_BW320_6G] = ARRAY_SIZE(dpd_6g_ch_list_bw320);
++		break;
++	case 0x7992:
++		dev->prek.rev  = mt7992_prek_rev;
++		dev->prek.dpd_ch_num[DPD_CH_NUM_BW80_5G] = ARRAY_SIZE(dpd_5g_ch_list_bw80);
++		/* 6g is not used in current sku */
++		dev->prek.dpd_ch_num[DPD_CH_NUM_BW20_6G] = 0;
++		dev->prek.dpd_ch_num[DPD_CH_NUM_BW80_6G] = 0;
++		dev->prek.dpd_ch_num[DPD_CH_NUM_BW160_6G] = 0;
++		break;
++	default:
++		dev->prek.rev  = mt7996_prek_rev;
++		break;
++	}
++}
++
+ static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
+ {
+ 	struct mt76_dev *mdev = &dev->mt76;
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 8f0f87b6..3e9992a3 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -67,6 +67,8 @@ enum mt7996_eeprom_field {
+ 
+ extern const struct ieee80211_channel dpd_2g_ch_list_bw20[];
+ extern const u32 dpd_2g_bw20_ch_num;
++extern const struct ieee80211_channel dpd_5g_skip_ch_list[];
++extern const u32 dpd_5g_skip_ch_num;
+ extern const struct ieee80211_channel dpd_5g_ch_list_bw160[];
+ extern const u32 dpd_5g_bw160_ch_num;
+ extern const struct ieee80211_channel dpd_6g_ch_list_bw160[];
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 55e8cb1e..4598d815 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3775,7 +3775,8 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 		chan_list_size = mphy->sband_5g.sband.n_channels;
+ 		base_offset += dpd_size_2g;
+ 		if (bw == NL80211_CHAN_WIDTH_160) {
+-			base_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++			base_offset += (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
++				       DPD_PER_CH_BW20_SIZE;
+ 			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
+ 			cal_id = RF_DPD_FLAT_5G_MEM_CAL;
+ 			chan_list = dpd_5g_ch_list_bw160;
+@@ -3784,6 +3785,9 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 			/* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
+ 			channel -= 2;
+ 		}
++		if (channel >= dpd_5g_skip_ch_list[0].hw_value &&
++		    channel <= dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
++			return 0;
+ 		break;
+ 	case NL80211_BAND_6GHZ:
+ 		dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
+@@ -3823,6 +3827,10 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 	if (idx == chan_list_size)
+ 		return -EINVAL;
+ 
++	if (band == NL80211_BAND_5GHZ && bw != NL80211_CHAN_WIDTH_160 &&
++	    channel > dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
++		idx -= dpd_5g_skip_ch_num;
++
+ 	cal += MT_EE_CAL_GROUP_SIZE + base_offset + idx * per_chan_size;
+ 
+ 	for (i = 0; i < per_chan_size / MT_EE_CAL_UNIT; i++) {
+diff --git a/mt7996/testmode.c b/mt7996/testmode.c
+index 2fb36a97..0dc6629d 100644
+--- a/mt7996/testmode.c
++++ b/mt7996/testmode.c
+@@ -531,6 +531,11 @@ mt7996_tm_dpd_prek_send_req(struct mt7996_phy *phy, struct mt7996_tm_req *req,
+ 	memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
+ 
+ 	for (i = 0; i < channel_size; i++) {
++		if (chan_list[i].band == NL80211_BAND_5GHZ &&
++		    chan_list[i].hw_value >= dpd_5g_skip_ch_list[0].hw_value &&
++		    chan_list[i].hw_value <= dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
++			continue;
++
+ 		memcpy(chandef->chan, &chan_list[i], sizeof(struct ieee80211_channel));
+ 		chandef->width = width;
+ 
+@@ -612,7 +617,8 @@ mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_5G_CAL);
+ 		if (ret)
+ 			return ret;
+-		wait_on_prek_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++		wait_on_prek_offset += (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
++				       DPD_PER_CH_BW20_SIZE;
+ 		wait_event_timeout(mdev->mcu.wait,
+ 				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
+ 
+@@ -868,6 +874,7 @@ mt7996_tm_get_center_chan(struct mt7996_phy *phy, struct cfg80211_chan_def *chan
+ 	const struct ieee80211_channel *chan = mphy->sband_5g.sband.channels;
+ 	u32 bitmap, i, offset, width_mhz, size = mphy->sband_5g.sband.n_channels;
+ 	u16 first_control = 0, control_chan = chandef->chan->hw_value;
++	bool not_first;
+ 
+ 	bitmap = mt7996_tm_bw_mapping(chandef->width, BW_MAP_NL_TO_CONTROL_BITMAP_5G);
+ 	if (!bitmap)
+@@ -877,7 +884,9 @@ mt7996_tm_get_center_chan(struct mt7996_phy *phy, struct cfg80211_chan_def *chan
+ 	offset = width_mhz / 10 - 2;
+ 
+ 	for (i = 0; i < size; i++) {
+-		if (!((1 << i) & bitmap))
++		not_first = (chandef->width != NL80211_CHAN_WIDTH_160) ?
++			    (i % bitmap) : (i >= 32) || !((1 << i) & bitmap);
++		if (not_first)
+ 			continue;
+ 
+ 		if (control_chan >= chan[i].hw_value)
+@@ -886,7 +895,7 @@ mt7996_tm_get_center_chan(struct mt7996_phy *phy, struct cfg80211_chan_def *chan
+ 			break;
+ 	}
+ 
+-	if (i == size || first_control == 0)
++	if (first_control == 0)
+ 		return control_chan;
+ 
+ 	return first_control + offset;
+diff --git a/mt7996/testmode.h b/mt7996/testmode.h
+index f97ccb26..ba1767ae 100644
+--- a/mt7996/testmode.h
++++ b/mt7996/testmode.h
+@@ -38,9 +38,9 @@ enum {
+ 	BF_CDBW_8080MHZ,
+ };
+ 
+-#define FIRST_CONTROL_CHAN_BITMAP_BW40		0x5555555
+-#define FIRST_CONTROL_CHAN_BITMAP_BW80		0x111111
+-#define FIRST_CONTROL_CHAN_BITMAP_BW160		0x100101
++#define FIRST_CONTROL_CHAN_BITMAP_BW40		2
++#define FIRST_CONTROL_CHAN_BITMAP_BW80		4
++#define FIRST_CONTROL_CHAN_BITMAP_BW160		0x10010101
+ 
+ enum bw_mapping_method {
+ 	BW_MAP_NL_TO_FW,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1036-mtk-wifi-mt76-mt7996-support-enable-disable-pp-featu.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1036-mtk-wifi-mt76-mt7996-support-enable-disable-pp-featu.patch
new file mode 100644
index 0000000..9bce324
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1036-mtk-wifi-mt76-mt7996-support-enable-disable-pp-featu.patch
@@ -0,0 +1,112 @@
+From 3ee3f424e835e9366924452f5f32d8ce094f2d7b Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 25 Sep 2023 19:20:49 +0800
+Subject: [PATCH 1036/1041] mtk: wifi: mt76: mt7996: support enable/disable pp
+ feature by nl80211 vendor commands
+
+User can enable/disable preamble puncture feature through hostapd
+configuration and hostapd_cli. Driver can receive the nl80211 vendor
+message and convert it to mcu commands.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/vendor.c | 38 ++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 12 ++++++++++++
+ 2 files changed, 50 insertions(+)
+
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index c7fd3278..9732ed28 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -107,6 +107,11 @@ background_radar_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BACKGROUND_RADAR_CTRL] = {
+ 	[MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MODE] = {.type = NLA_U8 },
+ };
+ 
++static struct nla_policy
++pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
++	[MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ 	u8 idx;
+ 	u8 addr[ETH_ALEN];
+@@ -877,6 +882,28 @@ static int mt7996_vendor_background_radar_mode_ctrl(struct wiphy *wiphy,
+ 	return mt7996_mcu_rdd_background_disable_timer(dev, !!background_radar_mode);
+ }
+ 
++static int mt7996_vendor_pp_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
++				 const void *data, int data_len)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_PP_CTRL];
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	int err;
++	u8 val8;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_PP_CTRL_MAX, data, data_len,
++			pp_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (tb[MTK_VENDOR_ATTR_PP_MODE]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_PP_MODE]);
++		err = mt7996_mcu_set_pp_en(phy, !!val8, 0, 0);
++	}
++
++	return err;
++}
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -982,6 +1009,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = background_radar_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_BACKGROUND_RADAR_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_PP_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_pp_ctrl,
++		.policy = pp_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_PP_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 920b6e6a..98128965 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
+ 	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ 	MTK_NL80211_VENDOR_SUBCMD_BACKGROUND_RADAR_CTRL = 0xcb,
++	MTK_NL80211_VENDOR_SUBCMD_PP_CTRL = 0xcc,
+ };
+ 
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -214,6 +215,17 @@ enum mtk_vendor_attr_ibf_dump {
+ 		NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
+ };
+ 
++enum mtk_vendor_attr_pp_ctrl {
++	MTK_VENDOR_ATTR_PP_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_PP_MODE,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_PP_CTRL,
++	MTK_VENDOR_ATTR_PP_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_PP_CTRL - 1
++};
++
+ #endif
+ 
+ #endif
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1037-mtk-wifi-mt76-testmode-add-kite-testmode-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1037-mtk-wifi-mt76-testmode-add-kite-testmode-support.patch
new file mode 100644
index 0000000..d3e9daf
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1037-mtk-wifi-mt76-testmode-add-kite-testmode-support.patch
@@ -0,0 +1,598 @@
+From 11a74db98d3f18b7d9ce7f2837079172a8b7d159 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 12 Oct 2023 16:17:33 +0800
+Subject: [PATCH 1037/1041] mtk: wifi: mt76: testmode: add kite testmode
+ support
+
+Add Kite testmode support
+1. avoid entering connac 2 testmode flow in kite
+2. refactor prek implementation for handling chip difference
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c   | 63 +++++++++++++-----------------
+ mt7996/eeprom.h   | 81 +++++++++++++++++++++++++++------------
+ mt7996/mcu.c      | 48 ++++++++++++++---------
+ mt7996/mt7996.h   | 18 ++++++++-
+ mt7996/testmode.c | 97 ++++++++++++++++++++++++++++-------------------
+ testmode.c        | 11 ++++--
+ 6 files changed, 198 insertions(+), 120 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index cff1b875..9fef7035 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -29,12 +29,39 @@ const struct ieee80211_channel dpd_5g_skip_ch_list[] = {
+ 	CHAN5G(96, 5480)
+ };
+ 
++const struct ieee80211_channel dpd_5g_ch_list_bw80[] = {
++	CHAN5G(42, 5210),
++	CHAN5G(58, 5290),
++	CHAN5G(106, 5530),
++	CHAN5G(122, 5610),
++	CHAN5G(138, 5690),
++	CHAN5G(155, 5775),
++	CHAN5G(171, 5855)
++};
++
+ const struct ieee80211_channel dpd_5g_ch_list_bw160[] = {
+ 	CHAN5G(50, 5250),
+ 	CHAN5G(114, 5570),
+ 	CHAN5G(163, 5815)
+ };
+ 
++const struct ieee80211_channel dpd_6g_ch_list_bw80[] = {
++	CHAN6G(7, 5985),
++	CHAN6G(23, 6065),
++	CHAN6G(39, 6145),
++	CHAN6G(55, 6225),
++	CHAN6G(71, 6305),
++	CHAN6G(87, 6385),
++	CHAN6G(103, 6465),
++	CHAN6G(119, 6545),
++	CHAN6G(135, 6625),
++	CHAN6G(151, 6705),
++	CHAN6G(167, 6785),
++	CHAN6G(183, 6865),
++	CHAN6G(199, 6945),
++	CHAN6G(215, 7025)
++};
++
+ const struct ieee80211_channel dpd_6g_ch_list_bw160[] = {
+ 	CHAN6G(15, 6025),
+ 	CHAN6G(47, 6185),
+@@ -54,12 +81,6 @@ const struct ieee80211_channel dpd_6g_ch_list_bw320[] = {
+ 	CHAN6G(191, 6905)
+ };
+ 
+-const u32 dpd_2g_bw20_ch_num = ARRAY_SIZE(dpd_2g_ch_list_bw20);
+-const u32 dpd_5g_skip_ch_num = ARRAY_SIZE(dpd_5g_skip_ch_list);
+-const u32 dpd_5g_bw160_ch_num = ARRAY_SIZE(dpd_5g_ch_list_bw160);
+-const u32 dpd_6g_bw160_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw160);
+-const u32 dpd_6g_bw320_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw320);
+-
+ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ {
+ #define FEM_INT				0
+@@ -126,36 +147,6 @@ const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ 	}
+ }
+ 
+-int
+-mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band)
+-{
+-	/* handle different sku */
+-	static const u8 band_to_idx[] = {
+-		[NL80211_BAND_2GHZ] = MT_BAND0,
+-		[NL80211_BAND_5GHZ] = MT_BAND1,
+-		[NL80211_BAND_6GHZ] = MT_BAND2,
+-	};
+-	struct mt7996_phy *phy = __mt7996_phy(dev, band_to_idx[band]);
+-	struct mt76_phy *mphy;
+-	int dpd_size;
+-
+-	if (!phy)
+-		return 0;
+-
+-	mphy = phy->mt76;
+-
+-	if (band == NL80211_BAND_2GHZ)
+-		dpd_size = dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
+-	else if (band == NL80211_BAND_5GHZ)
+-		dpd_size = (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
+-			   DPD_PER_CH_BW20_SIZE + dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
+-	else
+-		dpd_size = mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
+-			   (dpd_6g_bw160_ch_num + dpd_6g_bw320_ch_num) * DPD_PER_CH_GT_BW20_SIZE;
+-
+-	return dpd_size;
+-}
+-
+ static int
+ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+ {
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 3e9992a3..0d05e75e 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -45,36 +45,69 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CAL_DPD			GENMASK(5, 3)
+ 
+ #define MT_EE_CAL_UNIT				1024
+-#define MT_EE_CAL_GROUP_SIZE_2G			(4 * MT_EE_CAL_UNIT)
+-#define MT_EE_CAL_GROUP_SIZE_5G			(45 * MT_EE_CAL_UNIT)
+-#define MT_EE_CAL_GROUP_SIZE_6G			(125 * MT_EE_CAL_UNIT)
+-#define MT_EE_CAL_ADCDCOC_SIZE_2G		(4 * 4)
+-#define MT_EE_CAL_ADCDCOC_SIZE_5G		(4 * 4)
+-#define MT_EE_CAL_ADCDCOC_SIZE_6G		(4 * 5)
+-#define MT_EE_CAL_GROUP_SIZE			(MT_EE_CAL_GROUP_SIZE_2G + \
+-						 MT_EE_CAL_GROUP_SIZE_5G + \
+-						 MT_EE_CAL_GROUP_SIZE_6G + \
+-						 MT_EE_CAL_ADCDCOC_SIZE_2G + \
+-						 MT_EE_CAL_ADCDCOC_SIZE_5G + \
+-						 MT_EE_CAL_ADCDCOC_SIZE_6G)
+-
+-#define DPD_PER_CH_LEGACY_SIZE			(4 * MT_EE_CAL_UNIT)
+-#define DPD_PER_CH_MEM_SIZE			(13 * MT_EE_CAL_UNIT)
+-#define DPD_PER_CH_OTFG0_SIZE			(2 * MT_EE_CAL_UNIT)
+-#define DPD_PER_CH_BW20_SIZE			(DPD_PER_CH_LEGACY_SIZE + DPD_PER_CH_OTFG0_SIZE)
+-#define DPD_PER_CH_GT_BW20_SIZE			(DPD_PER_CH_MEM_SIZE + DPD_PER_CH_OTFG0_SIZE)
+-#define MT_EE_CAL_DPD_SIZE			(780 * MT_EE_CAL_UNIT)
++
++enum mt7996_prek_rev {
++	GROUP_SIZE_2G,
++	GROUP_SIZE_5G,
++	GROUP_SIZE_6G,
++	ADCDCOC_SIZE_2G,
++	ADCDCOC_SIZE_5G,
++	ADCDCOC_SIZE_6G,
++	DPD_LEGACY_SIZE,
++	DPD_MEM_SIZE,
++	DPD_OTFG0_SIZE,
++};
++
++static const u32 mt7996_prek_rev[] = {
++	[GROUP_SIZE_2G] =			4 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_5G] =			45 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_6G] =			125 * MT_EE_CAL_UNIT,
++	[ADCDCOC_SIZE_2G] =			4 * 4,
++	[ADCDCOC_SIZE_5G] =			4 * 4,
++	[ADCDCOC_SIZE_6G] =			4 * 5,
++	[DPD_LEGACY_SIZE] =			4 * MT_EE_CAL_UNIT,
++	[DPD_MEM_SIZE] =			13 * MT_EE_CAL_UNIT,
++	[DPD_OTFG0_SIZE] =			2 * MT_EE_CAL_UNIT,
++};
++
++/* kite 2/5g config */
++static const u32 mt7992_prek_rev[] = {
++	[GROUP_SIZE_2G] =			4 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_5G] =			110 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_6G] =			0,
++	[ADCDCOC_SIZE_2G] =			4 * 4,
++	[ADCDCOC_SIZE_5G] =			4 * 5,
++	[ADCDCOC_SIZE_6G] =			0,
++	[DPD_LEGACY_SIZE] =			5 * MT_EE_CAL_UNIT,
++	[DPD_MEM_SIZE] =			16 * MT_EE_CAL_UNIT,
++	[DPD_OTFG0_SIZE] =			2 * MT_EE_CAL_UNIT,
++};
+ 
+ extern const struct ieee80211_channel dpd_2g_ch_list_bw20[];
+-extern const u32 dpd_2g_bw20_ch_num;
+ extern const struct ieee80211_channel dpd_5g_skip_ch_list[];
+-extern const u32 dpd_5g_skip_ch_num;
++extern const struct ieee80211_channel dpd_5g_ch_list_bw80[];
+ extern const struct ieee80211_channel dpd_5g_ch_list_bw160[];
+-extern const u32 dpd_5g_bw160_ch_num;
++extern const struct ieee80211_channel dpd_6g_ch_list_bw80[];
+ extern const struct ieee80211_channel dpd_6g_ch_list_bw160[];
+-extern const u32 dpd_6g_bw160_ch_num;
+ extern const struct ieee80211_channel dpd_6g_ch_list_bw320[];
+-extern const u32 dpd_6g_bw320_ch_num;
++
++#define PREK(id)				(dev->prek.rev[(id)])
++#define DPD_CH_NUM(_type)			(dev->prek.dpd_ch_num[DPD_CH_NUM_##_type])
++#define MT_EE_CAL_GROUP_SIZE			(PREK(GROUP_SIZE_2G) + PREK(GROUP_SIZE_5G) + \
++						 PREK(GROUP_SIZE_6G) + PREK(ADCDCOC_SIZE_2G) + \
++						 PREK(ADCDCOC_SIZE_5G) + PREK(ADCDCOC_SIZE_6G))
++#define DPD_PER_CH_BW20_SIZE			(PREK(DPD_LEGACY_SIZE) + PREK(DPD_OTFG0_SIZE))
++#define DPD_PER_CH_GT_BW20_SIZE			(PREK(DPD_MEM_SIZE) + PREK(DPD_OTFG0_SIZE))
++#define MT_EE_CAL_DPD_SIZE_2G			(DPD_CH_NUM(BW20_2G) * DPD_PER_CH_BW20_SIZE)
++#define MT_EE_CAL_DPD_SIZE_5G			(DPD_CH_NUM(BW20_5G) * DPD_PER_CH_BW20_SIZE + \
++						 DPD_CH_NUM(BW80_5G) * DPD_PER_CH_GT_BW20_SIZE + \
++						 DPD_CH_NUM(BW160_5G) * DPD_PER_CH_GT_BW20_SIZE)
++#define MT_EE_CAL_DPD_SIZE_6G			(DPD_CH_NUM(BW20_6G) * DPD_PER_CH_BW20_SIZE + \
++						 DPD_CH_NUM(BW80_6G) * DPD_PER_CH_GT_BW20_SIZE + \
++						 DPD_CH_NUM(BW160_6G) * DPD_PER_CH_GT_BW20_SIZE + \
++						 DPD_CH_NUM(BW320_6G) * DPD_PER_CH_GT_BW20_SIZE)
++#define MT_EE_CAL_DPD_SIZE			(MT_EE_CAL_DPD_SIZE_2G + MT_EE_CAL_DPD_SIZE_5G + \
++						 MT_EE_CAL_DPD_SIZE_6G)
+ 
+ #define RF_DPD_FLAT_CAL				BIT(28)
+ #define RF_PRE_CAL				BIT(29)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 4598d815..a049ab71 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3744,13 +3744,11 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 	enum nl80211_chan_width bw = chandef->width;
+ 	const struct ieee80211_channel *chan_list;
+ 	u32 cal_id, chan_list_size, base_offset = 0, offs = MT_EE_DO_PRE_CAL;
+-	u32 dpd_size_2g, dpd_size_5g, per_chan_size = DPD_PER_CH_BW20_SIZE;
++	u32 per_chan_size = DPD_PER_CH_BW20_SIZE;
+ 	u16 channel = ieee80211_frequency_to_channel(chandef->center_freq1);
+ 	u8 dpd_mask, *cal = dev->cal, *eeprom = dev->mt76.eeprom.data;
+ 	int idx, i, ret;
+-
+-	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
+-	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
++	bool has_skip_ch = (band == NL80211_BAND_5GHZ);
+ 
+ 	switch (band) {
+ 	case NL80211_BAND_2GHZ:
+@@ -3766,27 +3764,35 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 			return 0;
+ 		cal_id = RF_DPD_FLAT_CAL;
+ 		chan_list = dpd_2g_ch_list_bw20;
+-		chan_list_size = dpd_2g_bw20_ch_num;
++		chan_list_size = DPD_CH_NUM(BW20_2G);
+ 		break;
+ 	case NL80211_BAND_5GHZ:
+ 		dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
+ 		cal_id = RF_DPD_FLAT_5G_CAL;
+ 		chan_list = mphy->sband_5g.sband.channels;
+ 		chan_list_size = mphy->sband_5g.sband.n_channels;
+-		base_offset += dpd_size_2g;
++		base_offset += MT_EE_CAL_DPD_SIZE_2G;
+ 		if (bw == NL80211_CHAN_WIDTH_160) {
+-			base_offset += (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
+-				       DPD_PER_CH_BW20_SIZE;
++			base_offset += DPD_CH_NUM(BW20_5G) * DPD_PER_CH_BW20_SIZE +
++				       DPD_CH_NUM(BW80_5G) * DPD_PER_CH_GT_BW20_SIZE;
+ 			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
+ 			cal_id = RF_DPD_FLAT_5G_MEM_CAL;
+ 			chan_list = dpd_5g_ch_list_bw160;
+-			chan_list_size = dpd_5g_bw160_ch_num;
++			chan_list_size = DPD_CH_NUM(BW160_5G);
++			has_skip_ch = false;
++		} else if (is_mt7992(&dev->mt76) && bw == NL80211_CHAN_WIDTH_80) {
++			base_offset += DPD_CH_NUM(BW20_5G) * DPD_PER_CH_BW20_SIZE;
++			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
++			cal_id = RF_DPD_FLAT_5G_MEM_CAL;
++			chan_list = dpd_5g_ch_list_bw80;
++			chan_list_size = DPD_CH_NUM(BW80_5G);
++			has_skip_ch = false;
+ 		} else if (bw > NL80211_CHAN_WIDTH_20) {
+ 			/* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
+ 			channel -= 2;
+ 		}
+ 		if (channel >= dpd_5g_skip_ch_list[0].hw_value &&
+-		    channel <= dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
++		    channel <= dpd_5g_skip_ch_list[DPD_CH_NUM(BW20_5G_SKIP) - 1].hw_value)
+ 			return 0;
+ 		break;
+ 	case NL80211_BAND_6GHZ:
+@@ -3794,20 +3800,27 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 		cal_id = RF_DPD_FLAT_6G_CAL;
+ 		chan_list = mphy->sband_6g.sband.channels;
+ 		chan_list_size = mphy->sband_6g.sband.n_channels;
+-		base_offset += dpd_size_2g + dpd_size_5g;
++		base_offset += MT_EE_CAL_DPD_SIZE_2G + MT_EE_CAL_DPD_SIZE_5G;
+ 		if (bw == NL80211_CHAN_WIDTH_160) {
+ 			base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
+ 			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
+ 			cal_id = RF_DPD_FLAT_6G_MEM_CAL;
+ 			chan_list = dpd_6g_ch_list_bw160;
+-			chan_list_size = dpd_6g_bw160_ch_num;
+-		} else if (bw == NL80211_CHAN_WIDTH_320) {
++			chan_list_size = DPD_CH_NUM(BW160_6G);
++		} else if (is_mt7996(&dev->mt76) && bw == NL80211_CHAN_WIDTH_320) {
+ 			base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
+-				       dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++				       DPD_CH_NUM(BW80_6G) * DPD_PER_CH_GT_BW20_SIZE +
++				       DPD_CH_NUM(BW160_6G) * DPD_PER_CH_GT_BW20_SIZE;
+ 			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
+ 			cal_id = RF_DPD_FLAT_6G_MEM_CAL;
+ 			chan_list = dpd_6g_ch_list_bw320;
+-			chan_list_size = dpd_6g_bw320_ch_num;
++			chan_list_size = DPD_CH_NUM(BW320_6G);
++		} else if (is_mt7992(&dev->mt76) && bw == NL80211_CHAN_WIDTH_80) {
++			base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
++			cal_id = RF_DPD_FLAT_6G_MEM_CAL;
++			chan_list = dpd_6g_ch_list_bw80;
++			chan_list_size = DPD_CH_NUM(BW80_6G);
+ 		} else if (bw > NL80211_CHAN_WIDTH_20) {
+ 			/* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
+ 			channel -= 2;
+@@ -3827,9 +3840,8 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
+ 	if (idx == chan_list_size)
+ 		return -EINVAL;
+ 
+-	if (band == NL80211_BAND_5GHZ && bw != NL80211_CHAN_WIDTH_160 &&
+-	    channel > dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
+-		idx -= dpd_5g_skip_ch_num;
++	if (has_skip_ch && channel > dpd_5g_skip_ch_list[DPD_CH_NUM(BW20_5G_SKIP) - 1].hw_value)
++		idx -= DPD_CH_NUM(BW20_5G_SKIP);
+ 
+ 	cal += MT_EE_CAL_GROUP_SIZE + base_offset + idx * per_chan_size;
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 339d9890..17cae7f5 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -195,6 +195,19 @@ struct mt7996_twt_flow {
+ 
+ DECLARE_EWMA(avg_signal, 10, 8)
+ 
++enum mt7996_dpd_ch_num {
++	DPD_CH_NUM_BW20_2G,
++	DPD_CH_NUM_BW20_5G,
++	DPD_CH_NUM_BW20_5G_SKIP,
++	DPD_CH_NUM_BW80_5G,
++	DPD_CH_NUM_BW160_5G,
++	DPD_CH_NUM_BW20_6G,
++	DPD_CH_NUM_BW80_6G,
++	DPD_CH_NUM_BW160_6G,
++	DPD_CH_NUM_BW320_6G,
++	DPD_CH_NUM_TYPE_MAX,
++};
++
+ struct mt7996_sta {
+ 	struct mt76_wcid wcid; /* must be first */
+ 
+@@ -456,6 +469,10 @@ struct mt7996_dev {
+ 
+ 	void *cal;
+ 	u32 cur_prek_offset;
++	struct {
++		const u32 *rev;
++		u8 dpd_ch_num[DPD_CH_NUM_TYPE_MAX];
++	} prek;
+ 
+ 	struct {
+ 		u16 table_mask;
+@@ -592,7 +609,6 @@ 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);
+-int mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band);
+ 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);
+diff --git a/mt7996/testmode.c b/mt7996/testmode.c
+index 0dc6629d..44ec84cc 100644
+--- a/mt7996/testmode.c
++++ b/mt7996/testmode.c
+@@ -434,7 +434,7 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
+ static int
+ mt7996_tm_group_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ {
+-	u8 *eeprom;
++	u8 *eeprom, do_precal;
+ 	u32 i, group_size, dpd_size, size, offs, *pre_cal;
+ 	int ret = 0;
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -462,6 +462,9 @@ mt7996_tm_group_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 	dpd_size = MT_EE_CAL_DPD_SIZE;
+ 	size = group_size + dpd_size;
+ 	offs = MT_EE_DO_PRE_CAL;
++	do_precal = (MT_EE_WIFI_CAL_GROUP_2G * !!PREK(GROUP_SIZE_2G)) |
++		    (MT_EE_WIFI_CAL_GROUP_5G * !!PREK(GROUP_SIZE_5G)) |
++		    (MT_EE_WIFI_CAL_GROUP_6G * !!PREK(GROUP_SIZE_6G));
+ 
+ 	switch (state) {
+ 	case MT76_TM_STATE_GROUP_PREK:
+@@ -476,13 +479,10 @@ mt7996_tm_group_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == group_size,
+ 				   30 * HZ);
+ 
+-		if (ret) {
++		if (ret)
+ 			dev_err(dev->mt76.dev, "Group Pre-cal: mcu send msg failed!\n");
+-			return ret;
+-		}
+-
+-		if (!ret)
+-			eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
++		else
++			eeprom[offs] |= do_precal;
+ 		break;
+ 	case MT76_TM_STATE_GROUP_PREK_DUMP:
+ 		pre_cal = (u32 *)dev->cal;
+@@ -520,10 +520,12 @@ mt7996_tm_dpd_prek_send_req(struct mt7996_phy *phy, struct mt7996_tm_req *req,
+ 	struct mt76_phy *mphy = phy->mt76;
+ 	struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
+ 	struct ieee80211_channel chan_backup;
+-	int i, ret;
++	int i, ret, skip_ch_num = DPD_CH_NUM(BW20_5G_SKIP);
+ 
+ 	if (!chan_list)
+ 		return -EOPNOTSUPP;
++	if (!channel_size)
++		return 0;
+ 
+ 	req->rf_test.op.rf.param.cal_param.func_data = cpu_to_le32(func_data);
+ 
+@@ -533,7 +535,7 @@ mt7996_tm_dpd_prek_send_req(struct mt7996_phy *phy, struct mt7996_tm_req *req,
+ 	for (i = 0; i < channel_size; i++) {
+ 		if (chan_list[i].band == NL80211_BAND_5GHZ &&
+ 		    chan_list[i].hw_value >= dpd_5g_skip_ch_list[0].hw_value &&
+-		    chan_list[i].hw_value <= dpd_5g_skip_ch_list[dpd_5g_skip_ch_num - 1].hw_value)
++		    chan_list[i].hw_value <= dpd_5g_skip_ch_list[skip_ch_num - 1].hw_value)
+ 			continue;
+ 
+ 		memcpy(chandef->chan, &chan_list[i], sizeof(struct ieee80211_channel));
+@@ -602,11 +604,11 @@ mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 	switch (state) {
+ 	case MT76_TM_STATE_DPD_2G:
+ 		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_2g_ch_list_bw20,
+-						  dpd_2g_bw20_ch_num,
++						  DPD_CH_NUM(BW20_2G),
+ 						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_CAL);
+-		wait_on_prek_offset += dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW20_2G) * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		do_precal = MT_EE_WIFI_CAL_DPD_2G;
+ 		break;
+@@ -617,18 +619,27 @@ mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_5G_CAL);
+ 		if (ret)
+ 			return ret;
+-		wait_on_prek_offset += (mphy->sband_5g.sband.n_channels - dpd_5g_skip_ch_num) *
+-				       DPD_PER_CH_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW20_5G) * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
++
++		/* 5g channel bw80 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_5g_ch_list_bw80,
++						  DPD_CH_NUM(BW80_5G),
++						  NL80211_CHAN_WIDTH_80, RF_DPD_FLAT_5G_MEM_CAL);
++		if (ret)
++			return ret;
++		wait_on_prek_offset += DPD_CH_NUM(BW80_5G) * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		/* 5g channel bw160 calibration */
+ 		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_5g_ch_list_bw160,
+-						  dpd_5g_bw160_ch_num,
++						  DPD_CH_NUM(BW160_5G),
+ 						  NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_5G_MEM_CAL);
+-		wait_on_prek_offset += dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW160_5G) * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		do_precal = MT_EE_WIFI_CAL_DPD_5G;
+ 		break;
+@@ -639,27 +650,37 @@ mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
+ 						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_6G_CAL);
+ 		if (ret)
+ 			return ret;
+-		wait_on_prek_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW20_6G) * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
++
++		/* 6g channel bw80 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw80,
++						  DPD_CH_NUM(BW80_6G),
++						  NL80211_CHAN_WIDTH_80, RF_DPD_FLAT_6G_MEM_CAL);
++		if (ret)
++			return ret;
++		wait_on_prek_offset += DPD_CH_NUM(BW80_6G) * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		/* 6g channel bw160 calibration */
+ 		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw160,
+-						  dpd_6g_bw160_ch_num,
++						  DPD_CH_NUM(BW160_6G),
+ 						  NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_6G_MEM_CAL);
+ 		if (ret)
+ 			return ret;
+-		wait_on_prek_offset += dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW160_6G) * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		/* 6g channel bw320 calibration */
+ 		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw320,
+-						  dpd_6g_bw320_ch_num,
++						  DPD_CH_NUM(BW320_6G),
+ 						  NL80211_CHAN_WIDTH_320, RF_DPD_FLAT_6G_MEM_CAL);
+-		wait_on_prek_offset += dpd_6g_bw320_ch_num * DPD_PER_CH_GT_BW20_SIZE;
+-		wait_event_timeout(mdev->mcu.wait,
+-				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++		wait_on_prek_offset += DPD_CH_NUM(BW320_6G) * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == wait_on_prek_offset,
++				   30 * HZ);
+ 
+ 		do_precal = MT_EE_WIFI_CAL_DPD_6G;
+ 		break;
+@@ -732,9 +753,9 @@ mt7996_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int
+ 	eeprom = dev->mt76.eeprom.data;
+ 	offs = MT_EE_DO_PRE_CAL;
+ 
+-	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
+-	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
+-	dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
++	dpd_size_2g = MT_EE_CAL_DPD_SIZE_2G;
++	dpd_size_5g = MT_EE_CAL_DPD_SIZE_5G;
++	dpd_size_6g = MT_EE_CAL_DPD_SIZE_6G;
+ 
+ 	switch (type) {
+ 	case PREK_SYNC_ALL:
+@@ -810,9 +831,9 @@ mt7996_tm_re_cal_event(struct mt7996_dev *dev, struct mt7996_tm_rf_test_result *
+ 	u8 *pre_cal;
+ 
+ 	pre_cal = dev->cal;
+-	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
+-	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
+-	dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
++	dpd_size_2g = MT_EE_CAL_DPD_SIZE_2G;
++	dpd_size_5g = MT_EE_CAL_DPD_SIZE_5G;
++	dpd_size_6g = MT_EE_CAL_DPD_SIZE_6G;
+ 
+ 	cal_idx = le32_to_cpu(data->cal_idx);
+ 	cal_type = le32_to_cpu(data->cal_type);
+diff --git a/testmode.c b/testmode.c
+index 7b8f9e66..81b492a5 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -37,6 +37,11 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+ };
+ EXPORT_SYMBOL_GPL(mt76_tm_policy);
+ 
++static inline bool mt76_testmode_offload(struct mt76_dev *dev)
++{
++	return is_mt7996(dev) || is_mt7992(dev);
++}
++
+ void mt76_testmode_tx_pending(struct mt76_phy *phy)
+ {
+ 	struct mt76_testmode_data *td = &phy->test;
+@@ -197,7 +202,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+ 	u8 max_nss = hweight8(phy->antenna_mask);
+ 	int ret;
+ 
+-	if (is_mt7996(phy->dev))
++	if (mt76_testmode_offload(phy->dev))
+ 		return 0;
+ 
+ 	ret = mt76_testmode_alloc_skb(phy, td->tx_mpdu_len);
+@@ -293,7 +298,7 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
+ 	td->tx_done = 0;
+ 	td->tx_pending = td->tx_count;
+ 
+-	if (!is_mt7996(dev))
++	if (!mt76_testmode_offload(dev))
+ 		mt76_worker_schedule(&dev->tx_worker);
+ }
+ 
+@@ -303,7 +308,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
+ 	struct mt76_testmode_data *td = &phy->test;
+ 	struct mt76_dev *dev = phy->dev;
+ 
+-	if (is_mt7996(dev) && dev->test_ops->tx_stop) {
++	if (mt76_testmode_offload(dev) && dev->test_ops->tx_stop) {
+ 		dev->test_ops->tx_stop(phy);
+ 		return;
+ 	}
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1038-mtk-wifi-mt76-mt7996-assign-DEAUTH-to-ALTX-queue-for.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1038-mtk-wifi-mt76-mt7996-assign-DEAUTH-to-ALTX-queue-for.patch
new file mode 100644
index 0000000..00904cc
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1038-mtk-wifi-mt76-mt7996-assign-DEAUTH-to-ALTX-queue-for.patch
@@ -0,0 +1,42 @@
+From a5a57f5c031c978e44a180df423568ff725d7dc2 Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Tue, 14 Nov 2023 11:27:06 +0800
+Subject: [PATCH 1038/1041] mtk: wifi: mt76: mt7996: assign DEAUTH to ALTX
+ queue for CERT
+
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+---
+ mt7996/mac.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 27e5fb71..408a59c5 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -753,6 +753,8 @@ static void
+ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
+ 			    struct sk_buff *skb, struct ieee80211_key_conf *key)
+ {
++	struct mt76_phy *mphy =
++		mt76_dev_phy(&dev->mt76, le32_get_bits(txwi[1], MT_TXD1_TGID));
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+@@ -762,6 +764,14 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
+ 	u8 fc_type, fc_stype;
+ 	u32 val;
+ 
++	if (ieee80211_is_cert_mode(mphy->hw) && ieee80211_is_deauth(fc)) {
++		/* In WPA3 cert TC-4.8.1, the deauth must be transmitted without
++		 * considering PSM bit
++		 */
++		txwi[0] &= ~cpu_to_le32(MT_TXD0_Q_IDX);
++		txwi[0] |= cpu_to_le32(FIELD_PREP(MT_TXD0_Q_IDX, MT_LMAC_ALTX0));
++	}
++
+ 	if (ieee80211_is_action(fc) &&
+ 	    mgmt->u.action.category == WLAN_CATEGORY_BACK &&
+ 	    mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1039-mtk-wifi-mt76-mt7996-add-no_beacon-vendor-command-fo.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1039-mtk-wifi-mt76-mt7996-add-no_beacon-vendor-command-fo.patch
new file mode 100644
index 0000000..0e5a5bb
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1039-mtk-wifi-mt76-mt7996-add-no_beacon-vendor-command-fo.patch
@@ -0,0 +1,153 @@
+From 79d4e84364caca0772254c2a2dbfe82c8f905ab5 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Wed, 22 Nov 2023 22:42:09 +0800
+Subject: [PATCH 1039/1041] mtk: wifi: mt76: mt7996: add no_beacon vendor
+ command for cert
+
+Add the vendor command to disable/enable beacon
+
+[Usage]
+hostapd_cli -i <interface> no_beacon <value>
+<value>
+0: enable beacon
+1: disable beacon
+
+Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
+---
+ mt7996/mcu.c    | 11 +++++++++++
+ mt7996/mt7996.h |  1 +
+ mt7996/vendor.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 12 ++++++++++++
+ 4 files changed, 65 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a049ab71..695a7f54 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -5052,4 +5052,15 @@ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+ 		break;
+ 	}
+ }
++
++void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
++{
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct ieee80211_hw *hw = mvif->phy->mt76->hw;
++	u8 val = *((u8 *)data);
++
++	vif->bss_conf.enable_beacon = val;
++
++	mt7996_mcu_add_beacon(hw, vif, val);
++}
+ #endif
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 17cae7f5..6233b987 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -828,6 +828,7 @@ void mt7996_set_wireless_amsdu(struct ieee80211_hw *hw, u8 en);
+ void mt7996_mcu_set_mimo(struct mt7996_phy *phy);
+ int mt7996_set_muru_cfg(struct mt7996_phy *phy, u8 action, u8 val);
+ int mt7996_mcu_set_muru_cfg(struct mt7996_phy *phy, void *data);
++void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
+ #endif
+ 
+ int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 9732ed28..c87cc5c1 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -112,6 +112,11 @@ pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
+ 	[MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
+ };
+ 
++static const struct nla_policy
++beacon_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BEACON_CTRL] = {
++	[MTK_VENDOR_ATTR_BEACON_CTRL_MODE] = { .type = NLA_U8 },
++};
++
+ struct mt7996_amnt_data {
+ 	u8 idx;
+ 	u8 addr[ETH_ALEN];
+@@ -904,6 +909,31 @@ static int mt7996_vendor_pp_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return err;
+ }
+ 
++static int mt7996_vendor_beacon_ctrl(struct wiphy *wiphy,
++				     struct wireless_dev *wdev,
++				     const void *data,
++				     int data_len)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_BEACON_CTRL];
++	int err;
++	u8 val8;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_BEACON_CTRL_MAX, data, data_len,
++			beacon_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (tb[MTK_VENDOR_ATTR_BEACON_CTRL_MODE]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_BEACON_CTRL_MODE]);
++		ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
++				mt7996_set_beacon_vif, &val8);
++	}
++
++	return 0;
++}
++
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -1020,6 +1050,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = pp_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_PP_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_BEACON_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_beacon_ctrl,
++		.policy = beacon_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_BEACON_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 98128965..e7d88828 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -16,6 +16,7 @@ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ 	MTK_NL80211_VENDOR_SUBCMD_BACKGROUND_RADAR_CTRL = 0xcb,
+ 	MTK_NL80211_VENDOR_SUBCMD_PP_CTRL = 0xcc,
++	MTK_NL80211_VENDOR_SUBCMD_BEACON_CTRL = 0xcd,
+ };
+ 
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -226,6 +227,17 @@ enum mtk_vendor_attr_pp_ctrl {
+ 		NUM_MTK_VENDOR_ATTRS_PP_CTRL - 1
+ };
+ 
++enum mtk_vendor_attr_beacon_ctrl {
++	MTK_VENDOR_ATTR_BEACON_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_BEACON_CTRL_MODE,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_BEACON_CTRL,
++	MTK_VENDOR_ATTR_BEACON_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_BEACON_CTRL - 1
++};
++
+ #endif
+ 
+ #endif
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1040-mtk-wifi-mt76-mt7996-add-adie-efuse-merge-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1040-mtk-wifi-mt76-mt7996-add-adie-efuse-merge-support.patch
new file mode 100644
index 0000000..0bd9aa0
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1040-mtk-wifi-mt76-mt7996-add-adie-efuse-merge-support.patch
@@ -0,0 +1,209 @@
+From 0e4686ad6417415cf601ffaff2e64858b1b3d56e Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 24 Nov 2023 09:49:08 +0800
+Subject: [PATCH 1040/1041] mtk: wifi: mt76: mt7996: add adie efuse merge
+ support
+
+Merge adie-dependent parameters in efuse into eeprom after FT.
+Note that Eagle BE14000 is not considered yet.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c    |   6 +-
+ 2 files changed, 149 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 9fef7035..75e31238 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -461,6 +461,147 @@ static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
+ 	return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
+ }
+ 
++static int mt7996_apply_cal_free_data(struct mt7996_dev *dev)
++{
++#define MT_EE_CAL_FREE_MAX_SIZE		30
++#define MT_EE_7977BN_OFFSET		(0x1200 - 0x500)
++#define MT_EE_END_OFFSET		0xffff
++	enum adie_type {
++		ADIE_7975,
++		ADIE_7976,
++		ADIE_7977,
++		ADIE_7978,
++		ADIE_7979,
++	};
++	static const u16 adie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
++		[ADIE_7975] = {0x5cd, 0x5cf, 0x5d1, 0x5d3, 0x6c0, 0x6c1, 0x6c2, 0x6c3,
++			       0x7a1, 0x7a6, 0x7a8, 0x7aa, -1},
++		[ADIE_7976] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
++			       0x70, 0x71, 0x790, 0x791, 0x794, 0x795, 0x7a6, 0x7a8, 0x7aa, -1},
++		[ADIE_7977] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
++			       0x69, 0x6a, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, -1},
++		[ADIE_7978] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
++			       0x90, 0x91, 0x94, 0x95, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
++			       0x100, 0x101, 0x102, 0x103, 0x104, 0x105, -1},
++		[ADIE_7979] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
++			       0x69, 0x6a, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, -1},
++	};
++	static const u16 eep_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
++		[ADIE_7975] = {0x451, 0x453, 0x455, 0x457, 0x44c, 0x44d, 0x44e, 0x44f,
++			       0xba1, 0xba6, 0xba8, 0xbaa, -1},
++		[ADIE_7976] = {0x44c, 0x44d, 0x44e, 0x44f, 0x450,
++			       0x451, 0x453, 0x455, 0x457, 0x459,
++			       0x470, 0x471, 0xb90, 0xb91, 0xb94, 0xb95,
++			       0xba6, 0xba8, 0xbaa, -1},
++		[ADIE_7977] = {0x124c, 0x124d, 0x124e, 0x124f, 0x1250,
++			       0x1251, 0x1253, 0x1255, 0x1257, 0x1259,
++			       0x1269, 0x126a, 0x127a, 0x127b, 0x127c, 0x127d, 0x127e, -1},
++		[ADIE_7978] = {0x44c, 0x44d, 0x44e, 0x44f, 0x450,
++			       0x451, 0x453, 0x455, 0x457, 0x459,
++			       0xb90, 0xb91, 0xb94, 0xb95,
++			       0xba6, 0xba7, 0xba8, 0xba9, 0xbaa,
++			       0x480, 0x481, 0x482, 0x483, 0x484, 0x485, -1},
++		[ADIE_7979] = {0x124c, 0x124d, 0x124e, 0x124f, 0x1250,
++			       0x1251, 0x1253, 0x1255, 0x1257, 0x1259,
++			       0x1269, 0x126a, 0x127a, 0x127b, 0x127c, 0x127d, 0x127e, -1},
++	};
++	static const u16 adie_base_7996[] = {
++		0x400, 0x1e00, 0x1200
++	};
++	static const u16 adie_base_7992[] = {
++		0x400, 0x1200, 0x0
++	};
++	static const u16 *adie_offs[__MT_MAX_BAND];
++	static const u16 *eep_offs[__MT_MAX_BAND];
++	static const u16 *adie_base;
++	u8 *eeprom = dev->mt76.eeprom.data;
++	u8 buf[MT7996_EEPROM_BLOCK_SIZE];
++	int adie_id, band, i, ret;
++
++	switch (mt76_chip(&dev->mt76)) {
++	case 0x7990:
++		adie_base = adie_base_7996;
++		/* adie 0 */
++		if (dev->fem_type == MT7996_FEM_INT)
++			adie_id = ADIE_7975;
++		else
++			adie_id = ADIE_7976;
++		adie_offs[0] = adie_offs_list[adie_id];
++		eep_offs[0] = eep_offs_list[adie_id];
++
++		/* adie 1 */
++		if (dev->chip_sku != MT7996_SKU_404) {
++			adie_offs[1] = adie_offs_list[ADIE_7977];
++			eep_offs[1] = eep_offs_list[ADIE_7977];
++		}
++
++		/* adie 2 */
++		adie_offs[2] = adie_offs_list[ADIE_7977];
++		eep_offs[2] = eep_offs_list[ADIE_7977];
++		break;
++	case 0x7992:
++		adie_base = adie_base_7992;
++		/* adie 0 */
++		if (dev->chip_sku == MT7992_SKU_44 &&
++		    dev->fem_type != MT7996_FEM_EXT)
++			adie_id = ADIE_7975;
++		else if (dev->chip_sku == MT7992_SKU_24)
++			adie_id = ADIE_7978;
++		else
++			adie_id = ADIE_7976;
++		adie_offs[0] = adie_offs_list[adie_id];
++		eep_offs[0] = eep_offs_list[adie_id];
++
++		/* adie 1 */
++		if (dev->chip_sku == MT7992_SKU_44 &&
++		    dev->fem_type != MT7996_FEM_INT)
++			adie_id = ADIE_7977;
++		else if (dev->chip_sku != MT7992_SKU_23)
++			adie_id = ADIE_7979;
++		else
++			break;
++		adie_offs[1] = adie_offs_list[adie_id];
++		eep_offs[1] = eep_offs_list[adie_id];
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	for (band = 0; band < __MT_MAX_BAND; band++) {
++		u16 adie_offset, eep_offset;
++		u32 block_num, prev_block_num = -1;
++
++		if (!adie_offs[band])
++			continue;
++
++		for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
++			adie_offset = adie_offs[band][i] + adie_base[band];
++			eep_offset = eep_offs[band][i];
++			block_num = adie_offset / MT7996_EEPROM_BLOCK_SIZE;
++
++			if (adie_offs[band][i] == MT_EE_END_OFFSET)
++				break;
++
++			if (is_mt7996(&dev->mt76) && dev->chip_sku == MT7996_SKU_444 &&
++			    band == MT_BAND1)
++				eep_offset -= MT_EE_7977BN_OFFSET;
++
++			if (prev_block_num != block_num) {
++				ret = mt7996_mcu_get_eeprom(dev, adie_offset, buf);
++				if (ret) {
++					prev_block_num = -1;
++					continue;
++				}
++			}
++
++			eeprom[eep_offset] = buf[adie_offset % MT7996_EEPROM_BLOCK_SIZE];
++			prev_block_num = block_num;
++		}
++	}
++
++	return 0;
++}
++
+ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ {
+ 	int ret;
+@@ -486,6 +627,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	ret = mt7996_apply_cal_free_data(dev);
++	if (ret)
++		return ret;
++
+ 	ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);
+ 	if (ret < 0)
+ 		return ret;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 695a7f54..6364be35 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3615,7 +3615,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
+ 	};
+ 	struct sk_buff *skb;
+ 	bool valid;
+-	int ret;
++	int ret = 0;
+ 	u8 *buf = read_buf;
+ 
+ 	ret = mt76_mcu_send_and_get_msg(&dev->mt76,
+@@ -3633,11 +3633,13 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
+ 
+ 		skb_pull(skb, 48);
+ 		memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
++	} else {
++		ret = -EINVAL;
+ 	}
+ 
+ 	dev_kfree_skb(skb);
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1041-mtk-wifi-mt7996-add-Eagle-2adie-TBTC-BE14000-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1041-mtk-wifi-mt7996-add-Eagle-2adie-TBTC-BE14000-support.patch
new file mode 100644
index 0000000..861c9dc
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/1041-mtk-wifi-mt7996-add-Eagle-2adie-TBTC-BE14000-support.patch
@@ -0,0 +1,167 @@
+From 0b73b1e3d8790bfd9d9d362e7876866f631fec14 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Tue, 5 Dec 2023 16:48:33 +0800
+Subject: [PATCH 1041/1041] mtk: wifi: mt7996: add Eagle 2adie TBTC (BE14000)
+ support
+
+Add fwdl/default eeprom load support for Eagle 2 adie TBTC
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Add Eagle 2adie TBTC efuse merge
+Add Eagle 2adie TBTC group prek size
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.c |  8 ++++++--
+ mt7996/eeprom.h | 12 ++++++++++++
+ mt7996/init.c   |  6 ++++++
+ mt7996/mcu.c    |  5 +++++
+ mt7996/mt7996.h |  8 ++++++++
+ mt7996/regs.h   |  1 +
+ 6 files changed, 38 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 75e31238..e33acdfb 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -128,6 +128,8 @@ const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ 	case 0x7990:
+ 		if (dev->chip_sku == MT7996_SKU_404)
+ 			return MT7996_EEPROM_DEFAULT_404;
++		else if (dev->chip_sku == MT7996_SKU_233)
++			return MT7996_EEPROM_DEFAULT_233;
+ 		return MT7996_EEPROM_DEFAULT;
+ 	case 0x7992:
+ 		if (dev->chip_sku == MT7992_SKU_23) {
+@@ -415,6 +417,8 @@ static void mt7996_eeprom_init_precal(struct mt7996_dev *dev)
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
+ 		dev->prek.rev = mt7996_prek_rev;
++		if (dev->chip_sku == MT7996_SKU_233)
++			dev->prek.rev = mt7996_prek_rev_233;
+ 		/* 5g & 6g bw 80 dpd channel list is not used */
+ 		dev->prek.dpd_ch_num[DPD_CH_NUM_BW320_6G] = ARRAY_SIZE(dpd_6g_ch_list_bw320);
+ 		break;
+@@ -522,7 +526,7 @@ static int mt7996_apply_cal_free_data(struct mt7996_dev *dev)
+ 	case 0x7990:
+ 		adie_base = adie_base_7996;
+ 		/* adie 0 */
+-		if (dev->fem_type == MT7996_FEM_INT)
++		if (dev->fem_type == MT7996_FEM_INT && dev->chip_sku != MT7996_SKU_233)
+ 			adie_id = ADIE_7975;
+ 		else
+ 			adie_id = ADIE_7976;
+@@ -530,7 +534,7 @@ static int mt7996_apply_cal_free_data(struct mt7996_dev *dev)
+ 		eep_offs[0] = eep_offs_list[adie_id];
+ 
+ 		/* adie 1 */
+-		if (dev->chip_sku != MT7996_SKU_404) {
++		if (dev->chip_sku == MT7996_SKU_444) {
+ 			adie_offs[1] = adie_offs_list[ADIE_7977];
+ 			eep_offs[1] = eep_offs_list[ADIE_7977];
+ 		}
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 0d05e75e..cd866123 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -70,6 +70,18 @@ static const u32 mt7996_prek_rev[] = {
+ 	[DPD_OTFG0_SIZE] =			2 * MT_EE_CAL_UNIT,
+ };
+ 
++static const u32 mt7996_prek_rev_233[] = {
++	[GROUP_SIZE_2G] =			4 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_5G] =			44 * MT_EE_CAL_UNIT,
++	[GROUP_SIZE_6G] =			100 * MT_EE_CAL_UNIT,
++	[ADCDCOC_SIZE_2G] =			4 * 4,
++	[ADCDCOC_SIZE_5G] =			4 * 4,
++	[ADCDCOC_SIZE_6G] =			4 * 5,
++	[DPD_LEGACY_SIZE] =			4 * MT_EE_CAL_UNIT,
++	[DPD_MEM_SIZE] =			13 * MT_EE_CAL_UNIT,
++	[DPD_OTFG0_SIZE] =			2 * MT_EE_CAL_UNIT,
++};
++
+ /* kite 2/5g config */
+ static const u32 mt7992_prek_rev[] = {
+ 	[GROUP_SIZE_2G] =			4 * MT_EE_CAL_UNIT,
+diff --git a/mt7996/init.c b/mt7996/init.c
+index b3677e03..c7576ffe 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -910,6 +910,12 @@ int mt7996_get_chip_sku(struct mt7996_dev *dev)
+ 
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
++		if (FIELD_GET(MT_PAD_GPIO_2ADIE_TBTC, val)) {
++			dev->chip_sku = MT7996_SKU_233;
++			dev->fem_type = MT7996_FEM_INT;
++			return 0;
++		}
++
+ 		adie_comb = FIELD_GET(MT_PAD_GPIO_ADIE_COMB, val);
+ 		if (adie_comb <= 1)
+ 			dev->chip_sku = MT7996_SKU_444;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6364be35..c980f345 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -23,6 +23,11 @@
+ 			_fw = MT7992_##name;			\
+ 		break;						\
+ 	case 0x7990:						\
++		if ((_dev)->chip_sku == MT7996_SKU_233)		\
++			_fw = MT7996_##name##_233;		\
++		else						\
++			_fw = MT7996_##name;			\
++		break;						\
+ 	default:						\
+ 		_fw = MT7996_##name;				\
+ 		break;						\
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 6233b987..9bcb6ff8 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 MT7996_FIRMWARE_WA_233		"mediatek/mt7996/mt7996_wa_233.bin"
++#define MT7996_FIRMWARE_WM_233		"mediatek/mt7996/mt7996_wm_233.bin"
++#define MT7996_FIRMWARE_DSP_233		MT7996_FIRMWARE_DSP
++#define MT7996_FIRMWARE_WM_TM_233	"mediatek/mt7996/mt7996_wm_tm_233.bin"
++#define MT7996_ROM_PATCH_233		"mediatek/mt7996/mt7996_rom_patch_233.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"
+@@ -54,6 +60,7 @@
+ #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_233	"mediatek/mt7996/mt7996_eeprom_233.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_2i5i.bin"
+@@ -123,6 +130,7 @@ enum mt7996_fem_type {
+ enum mt7996_sku_type {
+ 	MT7996_SKU_404,
+ 	MT7996_SKU_444,
++	MT7996_SKU_233,
+ };
+ 
+ enum mt7992_sku_type {
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index aa04d8d2..8d1462a7 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -666,6 +666,7 @@ enum offs_rev {
+ 
+ #define MT_PAD_GPIO				0x700056f0
+ #define MT_PAD_GPIO_ADIE_COMB			GENMASK(16, 15)
++#define MT_PAD_GPIO_2ADIE_TBTC			BIT(19)
+ #define MT_PAD_GPIO_ADIE_COMB_7992		GENMASK(17, 16)
+ #define MT_PAD_GPIO_ADIE_NUM_7992		BIT(15)
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-mtk-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
similarity index 84%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-mtk-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
index d2800ea..a7a243d 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2000-mtk-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
@@ -1,22 +1,21 @@
-From cc82fae54b1efd7de07034bea7a883b9fb362799 Mon Sep 17 00:00:00 2001
+From d0983563a9735b4b4a59efefaeb7dd0c49425ec8 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 64/98] wifi: mt76: revert page_poll for kernel 5.4
+Subject: [PATCH 2000/2020] mtk: wifi: mt76: revert page_poll for kernel 5.4
 
 This reverts commit e8c10835cf062c577ddf426913788c39d30b4bd7.
 
-Change-Id: I4e5764fc545087f691fb4c2f43e7a9cefd1e1657
 ---
- dma.c         | 75 +++++++++++++++++++++++++++------------------------
- mac80211.c    | 57 ---------------------------------------
- mmio.c        | 56 ++++++++++++++++++++++++--------------
- mt76.h        | 22 +--------------
- mt7915/main.c | 26 +++++++-----------
- usb.c         | 43 ++++++++++++++---------------
- 6 files changed, 109 insertions(+), 170 deletions(-)
+ dma.c         | 86 +++++++++++++++++++++++++--------------------------
+ mac80211.c    | 57 ----------------------------------
+ mmio.c        | 52 ++++++++++++++++++++-----------
+ mt76.h        | 22 +------------
+ mt7915/main.c | 26 ++++++----------
+ usb.c         | 43 +++++++++++++-------------
+ 6 files changed, 110 insertions(+), 176 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index bb995e2..06b76ea 100644
+index be8e2aaa..028c2fd5 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -178,7 +178,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
@@ -28,7 +27,7 @@
  		kfree(t);
  	}
  	local_bh_enable();
-@@ -445,9 +445,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -452,9 +452,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  		if (!t)
  			return NULL;
  
@@ -41,7 +40,7 @@
  
  		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,
+@@ -464,9 +464,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 {
@@ -54,7 +53,7 @@
  	}
  
  done:
-@@ -626,11 +626,11 @@ free_skb:
+@@ -636,11 +636,11 @@ free_skb:
  }
  
  static int
@@ -69,7 +68,7 @@
  
  	if (!q->ndesc)
  		return 0;
-@@ -639,28 +639,29 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -649,28 +649,29 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
  
  	while (q->queued < q->ndesc - 1) {
  		struct mt76_queue_buf qbuf = {};
@@ -109,7 +108,7 @@
  			break;
  		}
  		frames++;
-@@ -704,7 +705,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -714,7 +715,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);
@@ -118,7 +117,7 @@
  
  		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)
+@@ -743,7 +744,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);
@@ -127,7 +126,7 @@
  		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,
+@@ -799,10 +800,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  	if (!q->entry)
  		return -ENOMEM;
  
@@ -138,7 +137,7 @@
  	ret = mt76_dma_wed_setup(dev, q, false);
  	if (ret)
  		return ret;
-@@ -811,6 +808,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -821,6 +818,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)
  {
@@ -146,7 +145,7 @@
  	void *buf;
  	bool more;
  
-@@ -825,7 +823,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -836,7 +834,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  			break;
  
  		if (!mt76_queue_is_wed_rro(q))
@@ -154,8 +153,8 @@
 +			skb_free_frag(buf);
  	} while (1);
  
- 	if (q->rx_head) {
-@@ -834,6 +832,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+ 	spin_lock_bh(&q->lock);
+@@ -846,6 +844,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  	}
  
  	spin_unlock_bh(&q->lock);
@@ -172,25 +171,36 @@
  }
  
  static void
-@@ -857,7 +865,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -868,15 +876,10 @@ 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 (!mt76_queue_is_wed_tx_free(q)) {
- 		mt76_dma_sync_idx(dev, q);
--		mt76_dma_rx_fill(dev, q, false);
+ 
+-	if (mt76_queue_is_wed_tx_free(q))
+-		return;
+-
+-	if (mtk_wed_device_active(&dev->mmio.wed) &&
+-	    mt76_queue_is_wed_rro(q))
+-		return;
+-
+-	mt76_dma_sync_idx(dev, q);
+-	mt76_dma_rx_fill(dev, q, false);
++	if (!mt76_queue_is_wed_tx_free(q)) {
++		mt76_dma_sync_idx(dev, q);
 +		mt76_dma_rx_fill(dev, q);
- 	}
++	}
  }
  
-@@ -875,7 +883,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+ static void
+@@ -893,7 +896,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 {
--		mt76_put_page_pool_buf(data, true);
+-		mt76_put_page_pool_buf(data, allow_direct);
 +		skb_free_frag(data);
  	}
  
  	if (more)
-@@ -948,7 +956,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -968,7 +971,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  			goto free_frag;
  
  		skb_reserve(skb, q->buf_offset);
@@ -198,11 +208,11 @@
  
  		*(u32 *)skb->cb = info;
  
-@@ -964,10 +971,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -984,10 +986,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		continue;
  
  free_frag:
--		mt76_put_page_pool_buf(data, true);
+-		mt76_put_page_pool_buf(data, allow_direct);
 +		skb_free_frag(data);
  	}
  
@@ -211,7 +221,7 @@
  	return done;
  }
  
-@@ -1012,7 +1019,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -1032,7 +1034,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);
@@ -220,7 +230,7 @@
  		napi_enable(&dev->napi[i]);
  	}
  
-@@ -1067,8 +1074,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -1101,8 +1103,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
  
  		netif_napi_del(&dev->napi[i]);
  		mt76_dma_rx_cleanup(dev, q);
@@ -230,7 +240,7 @@
  
  	if (mtk_wed_device_active(&dev->mmio.wed))
 diff --git a/mac80211.c b/mac80211.c
-index 9c582cb..3715c73 100644
+index f74f6e85..885577fc 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -4,7 +4,6 @@
@@ -241,7 +251,7 @@
  #include "mt76.h"
  
  static const struct ieee80211_channel mt76_channels_2ghz[] = {
-@@ -546,47 +545,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -566,47 +565,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
  }
  EXPORT_SYMBOL_GPL(mt76_unregister_phy);
  
@@ -289,7 +299,7 @@
  struct mt76_dev *
  mt76_alloc_device(struct device *pdev, unsigned int size,
  		  const struct ieee80211_ops *ops,
-@@ -1786,21 +1744,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1819,21 +1777,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  }
  EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
  
@@ -312,7 +322,7 @@
  {
  	struct ieee80211_hw *hw = phy->hw;
 diff --git a/mmio.c b/mmio.c
-index c346249..5fb8392 100644
+index c3e0e23e..6c28e27b 100644
 --- a/mmio.c
 +++ b/mmio.c
 @@ -89,8 +89,12 @@ EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
@@ -354,10 +364,9 @@
  
  	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;
+ 		dma_addr_t addr;
+-		u32 offset;
 +		struct page *page;
  		int token;
 -		void *buf;
@@ -379,30 +388,29 @@
 -		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,
++		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))) {
++
++		if (unlikely(dma_mapping_error(dev->dev, 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);
+ 
+ 		desc->buf0 = cpu_to_le32(addr);
+-		token = mt76_rx_token_consume(dev, buf, t, addr);
++		token = mt76_rx_token_consume(dev, ptr, t, addr);
  		if (token < 0) {
 -			mt76_put_page_pool_buf(buf, false);
-+			dma_unmap_single(dev->dma_dev, phy_addr,
++			dma_unmap_single(dev->dma_dev, 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)
+@@ -153,8 +171,6 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
  	return 0;
  
  unmap:
@@ -412,7 +420,7 @@
  
  	return -ENOMEM;
 diff --git a/mt76.h b/mt76.h
-index d59a1f5..3af97e5 100644
+index 2a7b0ed9..e7b798b2 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -245,7 +245,7 @@ struct mt76_queue {
@@ -424,7 +432,7 @@
  };
  
  struct mt76_mcu_ops {
-@@ -1566,7 +1566,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+@@ -1592,7 +1592,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);
  }
  
@@ -432,7 +440,7 @@
  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);
-@@ -1707,25 +1706,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+@@ -1738,25 +1737,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_txwi_cache *r, dma_addr_t phys);
@@ -459,10 +467,10 @@
  static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
  {
 diff --git a/mt7915/main.c b/mt7915/main.c
-index ba34c8e..4c80473 100644
+index df2d4279..a6768512 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
-@@ -1397,22 +1397,19 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
+@@ -1398,22 +1398,19 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
  			   struct ieee80211_vif *vif,
  			   u32 sset, u8 *data)
  {
@@ -491,7 +499,7 @@
  }
  
  static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
-@@ -1440,7 +1437,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
+@@ -1441,7 +1438,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
  		.idx = mvif->mt76.idx,
  	};
  	/* See mt7915_ampdu_stat_read_phy, etc */
@@ -500,7 +508,7 @@
  
  	mutex_lock(&dev->mt76.mutex);
  
-@@ -1552,12 +1549,9 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
+@@ -1553,12 +1550,9 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
  		return;
  
  	ei += wi.worker_stat_count;
@@ -517,7 +525,7 @@
  
  static void
 diff --git a/usb.c b/usb.c
-index 5e5c7bf..3e28171 100644
+index 5e5c7bf5..3e281715 100644
 --- a/usb.c
 +++ b/usb.c
 @@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-wifi-mt76-rework-wed-rx-flow.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-mtk-wifi-mt76-rework-wed-rx-flow.patch
similarity index 84%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-wifi-mt76-rework-wed-rx-flow.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-mtk-wifi-mt76-rework-wed-rx-flow.patch
index a0854af..68382a2 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-wifi-mt76-rework-wed-rx-flow.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2001-mtk-wifi-mt76-rework-wed-rx-flow.patch
@@ -1,22 +1,21 @@
-From 78b8b86fce85c8ff6fad935bd9bd8b2df0e151ab Mon Sep 17 00:00:00 2001
+From 9601aeb0a394a557c038fdac877ada4620e06f61 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
+Subject: [PATCH 2001/2020] mtk: 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 +++++----
+ mmio.c          |  57 ++++++++++++++--------
+ mt76.h          |  25 ++++++----
  mt7915/mmio.c   |   3 +-
  mt7915/mt7915.h |   1 +
  tx.c            |  16 +++----
- 7 files changed, 143 insertions(+), 85 deletions(-)
+ 7 files changed, 144 insertions(+), 85 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 06b76ea..f48ec57 100644
+index 028c2fd5..16cb23b4 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -64,17 +64,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
@@ -54,8 +53,8 @@
 -	struct mt76_txwi_cache *t = NULL;
 +	struct mt76_rxwi_cache *r = NULL;
  
--	spin_lock(&dev->wed_lock);
-+	spin_lock(&dev->lock);
+-	spin_lock_bh(&dev->wed_lock);
++	spin_lock_bh(&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,
@@ -63,8 +62,8 @@
 -		list_del(&t->list);
 +		list_del(&r->list);
  	}
--	spin_unlock(&dev->wed_lock);
-+	spin_unlock(&dev->lock);
+-	spin_unlock_bh(&dev->wed_lock);
++	spin_unlock_bh(&dev->lock);
  
 -	return t;
 +	return r;
@@ -100,12 +99,12 @@
 +	if (!r)
  		return;
  
--	spin_lock(&dev->wed_lock);
+-	spin_lock_bh(&dev->wed_lock);
 -	list_add(&t->list, &dev->rxwi_cache);
--	spin_unlock(&dev->wed_lock);
-+	spin_lock(&dev->lock);
+-	spin_unlock_bh(&dev->wed_lock);
++	spin_lock_bh(&dev->lock);
 +	list_add(&r->list, &dev->rxwi_cache);
-+	spin_unlock(&dev->lock);
++	spin_unlock_bh(&dev->lock);
  }
  EXPORT_SYMBOL_GPL(mt76_put_rxwi);
  
@@ -139,10 +138,10 @@
  	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);
+ 	u32 buf1 = 0, ctrl;
+@@ -251,13 +251,15 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ #endif
  
  	if (mt76_queue_is_wed_rx(q)) {
 -		txwi = mt76_get_rxwi(dev);
@@ -162,7 +161,7 @@
  			return -ENOMEM;
  		}
  
-@@ -270,7 +272,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -273,7 +275,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;
@@ -171,7 +170,7 @@
  	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)
+@@ -422,7 +424,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,
@@ -180,9 +179,9 @@
  {
  	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,
+@@ -447,20 +449,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);
@@ -241,7 +240,7 @@
  		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,
+@@ -497,7 +532,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
  	q->tail = (q->tail + 1) % q->ndesc;
  	q->queued--;
  
@@ -250,7 +249,7 @@
  }
  
  static int
-@@ -658,7 +693,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -668,7 +703,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
  done:
  		qbuf.len = len - offset;
  		qbuf.skip_unmap = false;
@@ -260,10 +259,10 @@
  					 DMA_FROM_DEVICE);
  			skb_free_frag(buf);
 diff --git a/mac80211.c b/mac80211.c
-index 3715c73..4552bc2 100644
+index 885577fc..ff5f4853 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -575,7 +575,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -595,7 +595,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);
@@ -271,7 +270,7 @@
  	mutex_init(&dev->mutex);
  	init_waitqueue_head(&dev->tx_wait);
  
-@@ -608,6 +607,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -628,6 +627,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;
@@ -280,7 +279,7 @@
  	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
+index 6c28e27b..b792a7bd 100644
 --- a/mmio.c
 +++ b/mmio.c
 @@ -89,28 +89,45 @@ EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
@@ -340,14 +339,14 @@
  }
  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)
+@@ -125,18 +142,18 @@ 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;
+ 		dma_addr_t addr;
+ 		struct page *page;
  		int token;
  		void *ptr;
  
@@ -364,20 +363,20 @@
   			goto unmap;
  		}
  
-@@ -146,17 +162,17 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+@@ -146,17 +163,17 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
  
- 		if (unlikely(dma_mapping_error(dev->dev, phy_addr))) {
+ 		if (unlikely(dma_mapping_error(dev->dev, 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);
+ 		desc->buf0 = cpu_to_le32(addr);
+-		token = mt76_rx_token_consume(dev, ptr, t, addr);
++		token = mt76_rx_token_consume(dev, ptr, r, addr);
  		if (token < 0) {
- 			dma_unmap_single(dev->dma_dev, phy_addr,
+ 			dma_unmap_single(dev->dma_dev, addr,
  					 wed->wlan.rx_size, DMA_TO_DEVICE);
 -			__free_pages(page, get_order(length));
 -			mt76_put_rxwi(dev, t);
@@ -387,7 +386,7 @@
  		}
  
 diff --git a/mt76.h b/mt76.h
-index 3af97e5..b960f3d 100644
+index e7b798b2..17b39179 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -200,6 +200,7 @@ struct mt76_queue_entry {
@@ -398,7 +397,7 @@
  		struct urb *urb;
  		int buf_sz;
  	};
-@@ -410,10 +411,14 @@ struct mt76_txwi_cache {
+@@ -410,12 +411,16 @@ struct mt76_txwi_cache {
  	struct list_head list;
  	dma_addr_t dma_addr;
  
@@ -406,6 +405,9 @@
 -		struct sk_buff *skb;
 -		void *ptr;
 -	};
+-
+ 	unsigned long jiffies;
++
 +	struct sk_buff *skb;
 +};
 +
@@ -417,7 +419,7 @@
  };
  
  struct mt76_rx_tid {
-@@ -499,6 +504,7 @@ struct mt76_driver_ops {
+@@ -503,6 +508,7 @@ struct mt76_driver_ops {
  	u16 txwi_size;
  	u16 token_size;
  	u8 mcs_rates;
@@ -425,7 +427,7 @@
  
  	void (*update_survey)(struct mt76_phy *phy);
  
-@@ -858,7 +864,6 @@ struct mt76_dev {
+@@ -880,7 +886,6 @@ struct mt76_dev {
  
  	struct ieee80211_hw *hw;
  
@@ -433,7 +435,7 @@
  	spinlock_t lock;
  	spinlock_t cc_lock;
  
-@@ -1521,8 +1526,8 @@ mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
+@@ -1547,8 +1552,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);
@@ -444,7 +446,7 @@
  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 *
+@@ -1734,9 +1739,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);
@@ -457,19 +459,19 @@
  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
+index aff4f21e..9657636e 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,
+@@ -680,7 +680,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;
+ 	wed->wlan.reset_complete = mt76_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,
+@@ -886,6 +886,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
  				SURVEY_INFO_TIME_RX |
  				SURVEY_INFO_TIME_BSS_RX,
  		.token_size = MT7915_TOKEN_SIZE,
@@ -478,7 +480,7 @@
  		.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
+index 4727d9c7..ec224b46 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -62,6 +62,7 @@
@@ -490,10 +492,10 @@
  #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
+index 4596b367..e0c3e854 100644
 --- a/tx.c
 +++ b/tx.c
-@@ -843,16 +843,16 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+@@ -851,16 +851,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,
@@ -514,7 +516,7 @@
  	}
  	spin_unlock_bh(&dev->rx_token_lock);
  
-@@ -889,15 +889,15 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
+@@ -897,15 +897,15 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
  }
  EXPORT_SYMBOL_GPL(mt76_token_release);
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-mtk-wifi-mt76-wed-change-wed-token-init-size-to-adap.patch
similarity index 75%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-mtk-wifi-mt76-wed-change-wed-token-init-size-to-adap.patch
index 3dc3543..a4cf2c7 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2002-mtk-wifi-mt76-wed-change-wed-token-init-size-to-adap.patch
@@ -1,8 +1,8 @@
-From 1c0cb4fc09293006efdf8d1a9e92715a5705c29e Mon Sep 17 00:00:00 2001
+From cdecc4effebebbd6344eaf94516e8336afe70792 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 66/98] wifi: mt76: wed: change wed token init size to adapt
- wed3.0
+Subject: [PATCH 2002/2020] mtk: 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 74bf0de..3857c2a 100644
+index e0c3e854..1420ff71 100644
 --- a/tx.c
 +++ b/tx.c
-@@ -819,12 +819,16 @@ EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked);
+@@ -827,12 +827,16 @@ EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked);
  
  int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
  {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-mtk-wifi-mt76-add-random-early-drop-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-mtk-wifi-mt76-add-random-early-drop-support.patch
new file mode 100644
index 0000000..51ffcfe
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-mtk-wifi-mt76-add-random-early-drop-support.patch
@@ -0,0 +1,316 @@
+From e0fcc09873c502b3591934ad11d4382f78210b97 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 2003/2020] mtk: wifi: mt76: add random early drop support
+
+---
+ mt7996/debugfs.c     |  1 +
+ mt7996/mac.c         |  7 ++++
+ mt7996/mcu.c         | 81 ++++++++++++++++++++++++++++++++++++++++++--
+ mt7996/mcu.h         |  4 ++-
+ mt7996/mt7996.h      |  5 ++-
+ mt7996/mtk_debugfs.c | 23 +++++++++++++
+ mt7996/mtk_mcu.c     | 26 ++++++++++++++
+ mt7996/mtk_mcu.h     | 24 +++++++++++++
+ 8 files changed, 167 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 67c6bd09..223b655e 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -621,6 +621,7 @@ mt7996_tx_stats_show(struct seq_file *file, void *data)
+ 	seq_printf(file, "Tx attempts: %8u (MPDUs)\n", attempts);
+ 	seq_printf(file, "Tx success: %8u (MPDUs)\n", success);
+ 	seq_printf(file, "Tx PER: %u%%\n", per);
++	seq_printf(file, "Tx RED drop: %8u\n", phy->red_drop);
+ 
+ 	mt7996_txbf_stat_read_phy(phy, file);
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 408a59c5..a9d8f7dd 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1176,6 +1176,13 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 
+ 			wcid->stats.tx_retries += tx_retries;
+ 			wcid->stats.tx_failed += tx_failed;
++
++			if (FIELD_GET(MT_TXFREE_INFO_STAT, info) == 2) {
++				struct mt7996_phy *mphy =
++					__mt7996_phy(dev, wcid->phy_idx);
++
++				mphy->red_drop++;
++			}
+ 			continue;
+ 		}
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index c980f345..e893e79b 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3140,8 +3140,8 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	return mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+-				 MCU_WA_PARAM_RED, 0, 0);
++	return mt7996_mcu_red_config(dev,
++			mtk_wed_device_active(&dev->mt76.mmio.wed));
+ }
+ 
+ int mt7996_mcu_init(struct mt7996_dev *dev)
+@@ -3173,6 +3173,83 @@ out:
+ 	skb_queue_purge(&dev->mt76.mcu.res_q);
+ }
+ 
++static int mt7996_mcu_wa_red_config(struct mt7996_dev *dev)
++{
++#define RED_TOKEN_SRC_CNT	4
++#define RED_TOKEN_CONFIG	2
++	struct {
++		__le32 arg0;
++		__le32 arg1;
++		__le32 arg2;
++
++		u8 mode;
++		u8 version;
++		u8 _rsv[4];
++		__le16 len;
++
++		__le16 tcp_offset;
++		__le16 priority_offset;
++		__le16 token_per_src[RED_TOKEN_SRC_CNT];
++		__le16 token_thr_per_src[RED_TOKEN_SRC_CNT];
++
++		u8 _rsv2[604];
++	} __packed req = {
++		.arg0 = cpu_to_le32(MCU_WA_PARAM_RED_CONFIG),
++
++		.mode = RED_TOKEN_CONFIG,
++		.len = cpu_to_le16(sizeof(req) - sizeof(__le32) * 3),
++
++		.tcp_offset = cpu_to_le16(200),
++		.priority_offset = cpu_to_le16(255),
++	};
++	u8 i;
++
++	for (i = 0; i < RED_TOKEN_SRC_CNT; i++) {
++		req.token_per_src[i] = cpu_to_le16(MT7996_TOKEN_SIZE);
++		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);
++}
++
++int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable)
++{
++#define RED_DISABLE		0
++#define RED_BY_WA_ENABLE	2
++	struct {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 enable;
++		u8 __rsv2[3];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_VOW_RED_ENABLE),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.enable = enable ? RED_BY_WA_ENABLE : RED_DISABLE,
++	};
++	int ret;
++
++	ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
++				 sizeof(req), true);
++
++	if (ret)
++		return ret;
++
++	ret = mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
++				MCU_WA_PARAM_RED_EN, enable, 0);
++
++	if (ret || !enable)
++		return ret;
++
++	return mt7996_mcu_wa_red_config(dev);
++}
++
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans)
+ {
+ 	struct {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 398bf3d2..4fa399bc 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -346,8 +346,9 @@ enum {
+ enum {
+ 	MCU_WA_PARAM_PDMA_RX = 0x04,
+ 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
+-	MCU_WA_PARAM_RED = 0x0e,
++	MCU_WA_PARAM_RED_EN = 0x0e,
+ 	MCU_WA_PARAM_HW_PATH_HIF_VER = 0x2f,
++	MCU_WA_PARAM_RED_CONFIG = 0x40,
+ };
+ 
+ enum mcu_mmps_mode {
+@@ -919,6 +920,7 @@ enum {
+ 	UNI_VOW_DRR_CTRL,
+ 	UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
+ 	UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
++	UNI_VOW_RED_ENABLE = 0x18,
+ };
+ 
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 9bcb6ff8..e6a0b15a 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -351,6 +351,7 @@ struct mt7996_phy {
+ 	bool has_aux_rx;
+ 
+ 	struct mt7996_scs_ctrl scs_ctrl;
++	u32 red_drop;
+ 
+ 	u8 muru_onoff;
+ 
+@@ -696,6 +697,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, u16 val);
+ 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);
+ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
+ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+@@ -869,11 +871,12 @@ void mt7996_mcu_set_ppdu_tx_type(struct mt7996_phy *phy, u8 ppdu_type);
+ void mt7996_mcu_set_nusers_ofdma(struct mt7996_phy *phy, u8 type, u8 ofdma_user_cnt);
+ void mt7996_mcu_set_cert(struct mt7996_phy *phy, u8 type);
+ void mt7996_tm_update_channel(struct mt7996_phy *phy);
++
++int mt7996_mcu_set_vow_drr_dbg(struct mt7996_dev *dev, u32 val);
+ #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/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 0fdb911d..9cf3e6dc 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2919,6 +2919,27 @@ static int mt7996_muru_prot_thr_set(void *data, u64 val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_prot_thr, NULL,
+ 			 mt7996_muru_prot_thr_set, "%lld\n");
+ 
++static int
++mt7996_red_config_set(void *data, u64 val)
++{
++	struct mt7996_dev *dev = data;
++
++	return mt7996_mcu_red_config(dev, !!val);
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(fops_red_config, NULL,
++			 mt7996_red_config_set, "%lld\n");
++
++static int
++mt7996_vow_drr_dbg(void *data, u64 val)
++{
++	struct mt7996_dev *dev = data;
++
++	return mt7996_mcu_set_vow_drr_dbg(dev, (u32)val);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_vow_drr_dbg, NULL,
++			 mt7996_vow_drr_dbg, "%lld\n");
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2995,6 +3016,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 				    mt7996_wtbl_read);
+ 
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, mt7996_token_read);
++	debugfs_create_file("red", 0200, dir, dev, &fops_red_config);
++	debugfs_create_file("vow_drr_dbg", 0200, dir, dev, &fops_vow_drr_dbg);
+ 
+ 	debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable);
+ 	debugfs_create_file("scs_enable", 0200, dir, phy, &fops_scs_enable);
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index 2d8b08cd..6440efcf 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -1255,4 +1255,30 @@ void mt7996_mcu_set_cert(struct mt7996_phy *phy, u8 type)
+ 			  sizeof(req), false);
+ }
+ 
++int mt7996_mcu_set_vow_drr_dbg(struct mt7996_dev *dev, u32 val)
++{
++#define MT7996_VOW_DEBUG_MODE	0xe
++	struct {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 __rsv2[4];
++		__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(MT7996_VOW_DEBUG_MODE),
++		.val = cpu_to_le32(val),
++	};
++
++	if (val & ~VOW_DRR_DBG_FLAGS)
++		return -EINVAL;
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
++				 sizeof(req), true);
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index 881afef1..7d76bfea 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -1022,6 +1022,30 @@ enum muru_vendor_ctrl {
+ 	MU_CTRL_DL_USER_CNT,
+ 	MU_CTRL_UL_USER_CNT,
+ };
++
++enum {
++	VOW_DRR_DBG_DUMP_BMP = BIT(0),
++	VOW_DRR_DBG_EST_AT_PRINT = BIT(1),
++	VOW_DRR_DBG_ADJ_GLOBAL_THLD = BIT(21),
++	VOW_DRR_DBG_PRN_LOUD = BIT(22),
++	VOW_DRR_DBG_PRN_ADJ_STA = BIT(23),
++	VOW_DRR_DBG_FIX_CR = GENMASK(27, 24),
++	VOW_DRR_DBG_CLR_FIX_CR = BIT(28),
++	VOW_DRR_DBG_DISABLE = BIT(29),
++	VOW_DRR_DBG_DUMP_CR = BIT(30),
++	VOW_DRR_DBG_PRN = BIT(31)
++};
++
++#define VOW_DRR_DBG_FLAGS (VOW_DRR_DBG_DUMP_BMP |	\
++			  VOW_DRR_DBG_EST_AT_PRINT |	\
++			  VOW_DRR_DBG_ADJ_GLOBAL_THLD |	\
++			  VOW_DRR_DBG_PRN_LOUD |	\
++			  VOW_DRR_DBG_PRN_ADJ_STA |	\
++			  VOW_DRR_DBG_FIX_CR |		\
++			  VOW_DRR_DBG_CLR_FIX_CR |	\
++			  VOW_DRR_DBG_DISABLE |		\
++			  VOW_DRR_DBG_DUMP_CR |		\
++			  VOW_DRR_DBG_PRN)
+ #endif
+ 
+ #endif
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-wifi-mt76-add-random-early-drop-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-wifi-mt76-add-random-early-drop-support.patch
deleted file mode 100644
index e21fa8b..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2003-wifi-mt76-add-random-early-drop-support.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-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 67/98] wifi: mt76: add random early drop support
-
----
- mt7996/mcu.c    | 81 +++++++++++++++++++++++++++++++++++++++++++++++--
- mt7996/mcu.h    |  4 ++-
- mt7996/mt7996.h |  1 +
- 3 files changed, 83 insertions(+), 3 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index b8d26ec..6589610 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -3012,8 +3012,8 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
- 	if (ret)
- 		return ret;
- 
--	return mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
--				 MCU_WA_PARAM_RED, 0, 0);
-+	return mt7996_mcu_red_config(dev,
-+			mtk_wed_device_active(&dev->mt76.mmio.wed));
- }
- 
- int mt7996_mcu_init(struct mt7996_dev *dev)
-@@ -3045,6 +3045,83 @@ out:
- 	skb_queue_purge(&dev->mt76.mcu.res_q);
- }
- 
-+static int mt7996_mcu_wa_red_config(struct mt7996_dev *dev)
-+{
-+#define RED_TOKEN_SRC_CNT	4
-+#define RED_TOKEN_CONFIG	2
-+	struct {
-+		__le32 arg0;
-+		__le32 arg1;
-+		__le32 arg2;
-+
-+		u8 mode;
-+		u8 version;
-+		u8 _rsv[4];
-+		__le16 len;
-+
-+		__le16 tcp_offset;
-+		__le16 priority_offset;
-+		__le16 token_per_src[RED_TOKEN_SRC_CNT];
-+		__le16 token_thr_per_src[RED_TOKEN_SRC_CNT];
-+
-+		u8 _rsv2[604];
-+	} __packed req = {
-+		.arg0 = cpu_to_le32(MCU_WA_PARAM_RED_CONFIG),
-+
-+		.mode = RED_TOKEN_CONFIG,
-+		.len = cpu_to_le16(sizeof(req) - sizeof(__le32) * 3),
-+
-+		.tcp_offset = cpu_to_le16(200),
-+		.priority_offset = cpu_to_le16(255),
-+	};
-+	u8 i;
-+
-+	for (i = 0; i < RED_TOKEN_SRC_CNT; i++) {
-+		req.token_per_src[i] = cpu_to_le16(MT7996_TOKEN_SIZE);
-+		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);
-+}
-+
-+int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable)
-+{
-+#define RED_DISABLE		0
-+#define RED_BY_WA_ENABLE	2
-+	struct {
-+		u8 __rsv1[4];
-+
-+		__le16 tag;
-+		__le16 len;
-+		u8 enable;
-+		u8 __rsv2[3];
-+	} __packed req = {
-+		.tag = cpu_to_le16(UNI_VOW_RED_ENABLE),
-+		.len = cpu_to_le16(sizeof(req) - 4),
-+		.enable = enable ? RED_BY_WA_ENABLE : RED_DISABLE,
-+	};
-+	int ret;
-+
-+	ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
-+				 sizeof(req), true);
-+
-+	if (ret)
-+		return ret;
-+
-+	ret = mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
-+				MCU_WA_PARAM_RED_EN, enable, 0);
-+
-+	if (ret || !enable)
-+		return ret;
-+
-+	return mt7996_mcu_wa_red_config(dev);
-+}
-+
- int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans)
- {
- 	struct {
-diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index bb876f3..666216a 100644
---- a/mt7996/mcu.h
-+++ b/mt7996/mcu.h
-@@ -287,8 +287,9 @@ enum {
- enum {
- 	MCU_WA_PARAM_PDMA_RX = 0x04,
- 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
--	MCU_WA_PARAM_RED = 0x0e,
-+	MCU_WA_PARAM_RED_EN = 0x0e,
- 	MCU_WA_PARAM_HW_PATH_HIF_VER = 0x2f,
-+	MCU_WA_PARAM_RED_CONFIG = 0x40,
- };
- 
- enum mcu_mmps_mode {
-@@ -817,6 +818,7 @@ enum {
- 	UNI_VOW_DRR_CTRL,
- 	UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
- 	UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
-+	UNI_VOW_RED_ENABLE = 0x18,
- };
- 
- enum {
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 6775360..bba1364 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -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);
-+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);
- int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
- int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-mtk-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-mtk-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
new file mode 100644
index 0000000..8ddf523
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-mtk-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
@@ -0,0 +1,93 @@
+From 97a7decba0c4e4d3fb25a869caba6fd8928ffdab 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 2004/2020] mtk: 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>
+
+1. without this patch will delete wrong session id when delete ba.
+Due to fw change the cmd format.
+https://gerrit.mediatek.inc/c/neptune/firmware/bora/wifi/custom/+/7969193
+
+Signed-off-by: mtk27745 <rex.lu@mediatek.com>
+---
+ mt76.h       |  1 +
+ mt7996/mcu.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 47 insertions(+)
+
+diff --git a/mt76.h b/mt76.h
+index 17b39179..2ce1e84e 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -438,6 +438,7 @@ struct mt76_rx_tid {
+ 	u16 nframes;
+ 
+ 	u8 num;
++	u16 session_id;
+ 
+ 	u8 started:1, stopped:1, timer_pending:1;
+ 
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 4fa399bc..a2604192 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -298,6 +298,52 @@ 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 {
++	__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;
++	__le16 mld_id;
++	u8 tid;
++	u8 __rsv[3];
++} __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,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
deleted file mode 100644
index d9fe625..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
+++ /dev/null
@@ -1,425 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-mtk-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-mtk-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G.patch
new file mode 100644
index 0000000..f322d86
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-mtk-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G.patch
@@ -0,0 +1,68 @@
+From cd5a67a360ea7897a5129ae5b4b4c1fee73837dc 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 2005/2020] mtk: wifi: mt76 : wed : change pcie0 R5 to pcie1 to
+ get 6G ICS
+
+---
+ mt7996/dma.c  | 4 ++++
+ mt7996/init.c | 6 ++----
+ mt7996/mmio.c | 5 ++++-
+ 3 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 8e29ab06..40ab65f8 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -537,6 +537,10 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	if (mt7996_band_valid(dev, MT_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);
++			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 c7576ffe..10b17f7d 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -642,10 +642,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_TX_RX_DONE_EXT);
++		mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, MT_INT_TX_RX_DONE_EXT);
+ 	}
+ 
+ 	return 0;
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index d3d34f04..4814897c 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -532,12 +532,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_TX_RX_DONE_EXT);
+ 	} else {
+ 		mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ 		if (dev->hif2)
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch
deleted file mode 100644
index 306c6e6..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2005-wifi-mt76-wed-change-pcie0-R5-to-pcie1-to-get-6G-ICS.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-mtk-wifi-mt76-add-SER-support-for-wed3.0.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-mtk-wifi-mt76-add-SER-support-for-wed3.0.patch
new file mode 100644
index 0000000..d471b73
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-mtk-wifi-mt76-add-SER-support-for-wed3.0.patch
@@ -0,0 +1,41 @@
+From 4d9f1a03be245fcefd8567c5b3623de9f85945ae Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Tue, 23 May 2023 12:06:29 +0800
+Subject: [PATCH 2006/2020] mtk: wifi: mt76: add SER support for wed3.0
+
+---
+ dma.c         | 5 +++--
+ mt7996/mmio.c | 1 +
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 16cb23b4..dfce79fa 100644
+--- a/dma.c
++++ b/dma.c
+@@ -910,8 +910,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 (!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/mmio.c b/mt7996/mmio.c
+index 4814897c..488f5103 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -302,6 +302,7 @@ out:
+ 
+ 	return ret;
+ }
++
+ #endif
+ 
+ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch
deleted file mode 100644
index 7511279..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2006-wifi-mt76-mt7996-add-rro-elem-free-when-rmmod-wifi-m.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
similarity index 75%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
index 2688d54..575675d 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch
@@ -1,8 +1,8 @@
-From 50c902b8856af271bc5514d623ad09f7c3f2d880 Mon Sep 17 00:00:00 2001
+From 2ce94ab60b821db9a1f3368df1b24b4f7904a00b 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
+Subject: [PATCH 2007/2020] mtk: 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.
@@ -14,15 +14,14 @@
  1 file changed, 25 insertions(+), 2 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 141a97b..3983ebb 100644
+index dfce79fa..69333769 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,
- 	}
+@@ -448,9 +448,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ 	mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
  
  	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;
@@ -52,7 +51,7 @@
  		if (!r)
  			return NULL;
  
-@@ -965,7 +988,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -978,7 +1001,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		if (!data)
  			break;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-wifi-mt76-add-SER-support-for-wed3.0.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-wifi-mt76-add-SER-support-for-wed3.0.patch
deleted file mode 100644
index 2ba1f4e..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2007-wifi-mt76-add-SER-support-for-wed3.0.patch
+++ /dev/null
@@ -1,278 +0,0 @@
-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 71/98] wifi: mt76: add SER support for wed3.0
-
-Change-Id: I2711b9dc336fca9a1ae32a8fbf27810a7e27b1e3
----
- 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 f48ec57..141a97b 100644
---- a/dma.c
-+++ b/dma.c
-@@ -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 (!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 2397fe5..b2c7ae6 100644
---- a/mt7996/dma.c
-+++ b/mt7996/dma.c
-@@ -615,11 +615,35 @@ int mt7996_dma_init(struct mt7996_dev *dev)
- 	return 0;
- }
- 
-+static void mt7996_dma_wed_reset(struct mt7996_dev *dev)
-+{
-+	struct mt76_dev *mdev = &dev->mt76;
-+
-+	if (!test_bit(MT76_STATE_WED_RESET, &dev->mphy.state))
-+		return;
-+
-+	complete(&mdev->mmio.wed_reset);
-+
-+	if (!wait_for_completion_timeout(&dev->mt76.mmio.wed_reset_complete,
-+					 3 * HZ))
-+		dev_err(dev->mt76.dev, "wed reset complete timeout\n");
-+}
-+
-+static void
-+mt7996_dma_reset_tx_queue(struct mt7996_dev *dev, struct mt76_queue *q)
-+{
-+	mt76_queue_reset(dev, q);
-+	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
-+		mt76_dma_wed_setup(&dev->mt76, q, true);
-+}
-+
- void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
- {
- 	struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
- 	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_hif2 = &dev->mt76.mmio.wed_hif2;
- 	int i;
- 
- 	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
-@@ -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_hif2))
-+		mtk_wed_device_dma_reset(wed_hif2);
-+
-+	if (mtk_wed_device_active(wed))
-+		mtk_wed_device_dma_reset(wed);
-+
- 	mt7996_dma_disable(dev, force);
-+	mt7996_dma_wed_reset(dev);
- 
- 	/* reset hw queues */
- 	for (i = 0; i < __MT_TXQ_MAX; i++) {
--		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]);
-+			mt7996_dma_reset_tx_queue(dev, phy2->q_tx[i]);
- 		if (phy3)
--			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]);
- 
- 	mt76_for_each_q_rx(&dev->mt76, i) {
-+		if (mtk_wed_device_active(wed) &&
-+		    (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]);
- 	}
- 
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 60ca23b..22cff71 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -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) &&
-+		    mt76_queue_is_wed_rro(&mdev->q_rx[i]))
-+			continue;
-+
- 		if (mdev->q_rx[i].ndesc)
- 			napi_disable(&dev->mt76.napi[i]);
- 	}
-@@ -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) &&
-+		    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]);
-@@ -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_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);
-+
- 	ieee80211_stop_queues(mt76_hw(dev));
- 	if (phy2)
- 		ieee80211_stop_queues(phy2->mt76->hw);
-@@ -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) &&
-+		    mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
-+			continue;
-+
- 		napi_disable(&dev->mt76.napi[i]);
-+	}
- 	napi_disable(&dev->mt76.tx_napi);
- 
- 	mutex_lock(&dev->mt76.mutex);
-@@ -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)) {
-+		u32 wed_irq_mask = dev->mt76.mmio.irqmask |
-+				   MT_INT_RRO_RX_DONE |
-+				   MT_INT_TX_DONE_BAND2;
-+
-+		if (mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
-+			wed_irq_mask &= ~MT_INT_RX_DONE_RRO_IND;
-+
-+		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
-+
-+		mtk_wed_device_start_hwrro(&dev->mt76.mmio.wed, wed_irq_mask, true);
-+		mt7996_irq_enable(dev, wed_irq_mask);
-+		mt7996_irq_disable(dev, 0);
-+	}
-+
-+	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)
-@@ -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) &&
-+		    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 2e395d1..631d905 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -6,9 +6,11 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
-+#include <linux/rtnetlink.h>
- 
- #include "mt7996.h"
- #include "mac.h"
-+#include "mcu.h"
- #include "../trace.h"
- #include "../dma.h"
- 
-@@ -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);
-+	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
-+	struct mt76_phy *mphy = &dev->mphy;
-+	int ret;
-+
-+	ASSERT_RTNL();
-+
-+	if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
-+		return -EBUSY;
-+
-+	ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
-+				 mphy->band_idx);
-+	if (ret)
-+		goto out;
-+
-+	rtnl_unlock();
-+	if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) {
-+		dev_err(mdev->dev, "wed reset timeout\n");
-+		ret = -ETIMEDOUT;
-+	}
-+	rtnl_lock();
-+out:
-+	clear_bit(MT76_STATE_WED_RESET, &mphy->state);
-+
-+	return ret;
-+}
-+
-+static void mt7996_mmio_wed_reset_complete(struct mtk_wed_device *wed)
-+{
-+	struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-+
-+	complete(&dev->mmio.wed_reset_complete);
-+}
-+
-+#endif
-+
- int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
- 			 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;
-+	} else {
-+		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.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-mtk-wifi-mt76-mt7996-add-dma-mask-limitation.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-mtk-wifi-mt76-mt7996-add-dma-mask-limitation.patch
new file mode 100644
index 0000000..dce4540
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2008-mtk-wifi-mt76-mt7996-add-dma-mask-limitation.patch
@@ -0,0 +1,57 @@
+From 20990e5d6a405c24354d78e2632a8c0510613f18 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 2008/2020] mtk: wifi: mt76: mt7996: add dma mask limitation
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c  | 4 ++--
+ mmio.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 69333769..5bff27dd 100644
+--- a/dma.c
++++ b/dma.c
+@@ -490,7 +490,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;
+ 
+@@ -712,7 +712,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 b792a7bd..269fd932 100644
+--- a/mmio.c
++++ b/mmio.c
+@@ -144,14 +144,14 @@ u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+ 	for (i = 0; i < size; i++) {
+ 		struct mt76_rxwi_cache *r = mt76_get_rxwi(dev);
+ 		dma_addr_t addr;
+-		struct page *page;
+ 		int token;
+ 		void *ptr;
+ 
+ 		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;
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-mtk-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
similarity index 86%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-mtk-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
index 3295f14..197f001 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-mtk-wifi-mt76-mt7996-add-per-bss-statistic-info.patch
@@ -1,7 +1,7 @@
-From d97655d3fe3ddf2bbd508de52e207bc91d0115e2 Mon Sep 17 00:00:00 2001
+From f738720718ccb088c71be5dfa9bd5b9a2b7cb78e 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
+Subject: [PATCH 2009/2020] mtk: 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.
@@ -22,10 +22,10 @@
  3 files changed, 37 insertions(+), 5 deletions(-)
 
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 51649dd..20e14e7 100644
+index 10b17f7d..d807c357 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)
+@@ -390,6 +390,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);
@@ -34,7 +34,7 @@
  	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
+index 5a5b549a..939b0943 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -251,6 +251,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
@@ -46,11 +46,11 @@
  
  	mt7996_mac_wtbl_update(dev, idx,
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index bebd020..b2cb627 100644
+index e893e79b..c5167732 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)
- 
+@@ -521,6 +521,27 @@ mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rat
+ 	return 0;
  }
  
 +static inline void __mt7996_stat_to_netdev(struct mt76_phy *mphy,
@@ -77,7 +77,7 @@
  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)
+@@ -536,7 +557,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;
@@ -86,7 +86,7 @@
  
  		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)
+@@ -564,6 +585,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;
  
@@ -96,7 +96,7 @@
  				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)
+@@ -575,10 +599,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
  			if (!wcid)
  				break;
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch
deleted file mode 100644
index 675e4eb..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2009-wifi-mt76-drop-packet-based-on-ind_reason.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-mtk-wifi-mt76-mt7996-do-not-report-netdev-stats-on-m.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-mtk-wifi-mt76-mt7996-do-not-report-netdev-stats-on-m.patch
new file mode 100644
index 0000000..41093ff
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-mtk-wifi-mt76-mt7996-do-not-report-netdev-stats-on-m.patch
@@ -0,0 +1,37 @@
+From fc585381223ac634308f6c396e548a4b03c9c190 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 26 Oct 2023 17:27:43 +0800
+Subject: [PATCH 2010/2020] mtk: wifi: mt76: mt7996: do not report netdev stats
+ on monitor vif
+
+This fixes the following NULL pointer crash when enabling monitor mode:
+[  205.593158] Call trace:
+[  205.595597]  mt7996_mcu_rx_event+0x4a0/0x6e8 [mt7996e]
+[  205.600725]  mt7996_queue_rx_skb+0x6e4/0xfa0 [mt7996e]
+[  205.605851]  mt76_dma_rx_poll+0x384/0x420 [mt76]
+[  205.610459]  __napi_poll+0x38/0x1c0
+[  205.613935]  napi_threaded_poll+0x80/0xe8
+[  205.617934]  kthread+0x124/0x128
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/mcu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index c5167732..3116e664 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -537,6 +537,9 @@ static inline void __mt7996_stat_to_netdev(struct mt76_phy *mphy,
+ 				   drv_priv);
+ 		wdev = ieee80211_vif_to_wdev(vif);
+ 
++		if (vif->type == NL80211_IFTYPE_MONITOR)
++			return;
++
+ 		dev_sw_netstats_tx_add(wdev->netdev, tx_packets, tx_bytes);
+ 		dev_sw_netstats_rx_add(wdev->netdev, rx_packets, rx_bytes);
+ 	}
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch
deleted file mode 100644
index 6fe2cea..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2010-wifi-mt76-mt7996-add-rro-timeout-setting.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-mtk-wifi-mt76-mt7996-add-support-for-HW-ATF.patch
similarity index 68%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch
rename to autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-mtk-wifi-mt76-mt7996-add-support-for-HW-ATF.patch
index a581775..7e19302 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-wifi-mt76-mt7996-add-support-for-HW-ATF-initializati.patch
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-mtk-wifi-mt76-mt7996-add-support-for-HW-ATF.patch
@@ -1,21 +1,129 @@
-From dda3205c68ab3b38945f0066be5fc95ba067f3af Mon Sep 17 00:00:00 2001
+From 7768e810767e4ac6bb65f42ad459e84fbc22c6c0 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
+Subject: [PATCH 2011/2020] mtk: wifi: mt76: mt7996: add support for HW-ATF
 
 ---
- mt7996/init.c   |  43 ++++++++
- mt7996/mcu.c    | 263 +++++++++++++++++++++++++++++++++++++++++++-----
- mt7996/mcu.h    |   1 +
- mt7996/mt7996.h |  94 +++++++++++++++++
- 4 files changed, 376 insertions(+), 25 deletions(-)
+ mt7996/debugfs.c |  89 ++++++++++++++++
+ mt7996/init.c    |  43 ++++++++
+ mt7996/mac.c     |   6 ++
+ mt7996/mcu.c     | 265 ++++++++++++++++++++++++++++++++++++++++++-----
+ mt7996/mcu.h     |   1 +
+ mt7996/mt7996.h  |  96 ++++++++++++++++-
+ 6 files changed, 474 insertions(+), 26 deletions(-)
 
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 223b655e..3d514c44 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -863,6 +863,90 @@ mt7996_rf_regval_set(void *data, u64 val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get,
+ 			 mt7996_rf_regval_set, "0x%08llx\n");
+ 
++static int
++mt7996_vow_info_read(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt7996_vow_ctrl *vow = &dev->vow;
++	int i;
++
++	seq_printf(s, "VoW ATF Configuration:\n");
++	seq_printf(s, "ATF: %s\n", vow->atf_enable ? "enabled" : "disabled");
++	seq_printf(s, "WATF: %s\n", vow->watf_enable ? "enabled" : "disabled");
++	seq_printf(s, "Airtime Quantums (unit: 256 us)\n");
++	for (i = 0; i < VOW_DRR_QUANTUM_NUM; ++i)
++		seq_printf(s, "\tL%d: %hhu\n", i, vow->drr_quantum[i]);
++	seq_printf(s, "Max Airtime Deficit: %hhu (unit: 256 us)\n", vow->max_deficit);
++
++	return 0;
++}
++
++static int
++mt7996_atf_enable_get(void *data, u64 *val)
++{
++	struct mt7996_phy *phy = data;
++
++	*val = phy->dev->vow.atf_enable;
++
++	return 0;
++}
++
++static int
++mt7996_atf_enable_set(void *data, u64 val)
++{
++	struct mt7996_phy *phy = data;
++	struct mt7996_vow_ctrl *vow = &phy->dev->vow;
++	int ret;
++
++	vow->max_deficit = val ? 64 : 1;
++	ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND);
++	if (ret)
++		return ret;
++
++	vow->atf_enable = !!val;
++	return mt7996_mcu_set_vow_feature_ctrl(phy);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_atf_enable, mt7996_atf_enable_get,
++	                 mt7996_atf_enable_set, "%llu\n");
++
++static int
++mt7996_airtime_read(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt76_dev *mdev = &dev->mt76;
++	struct mt7996_vow_sta_ctrl *vow;
++	struct ieee80211_sta *sta;
++	struct mt7996_sta *msta;
++	struct mt76_wcid *wcid;
++	struct mt76_vif *vif;
++	u64 airtime;
++	u16 i;
++
++	seq_printf(s, "VoW Airtime Information:\n");
++	rcu_read_lock();
++	for (i = 1; i < MT7996_WTBL_STA; ++i) {
++		wcid = rcu_dereference(mdev->wcid[i]);
++		if (!wcid || !wcid->sta)
++			continue;
++
++		msta = container_of(wcid, struct mt7996_sta, wcid);
++		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
++		vow = &msta->vow;
++		vif = &msta->vif->mt76;
++
++		spin_lock_bh(&vow->lock);
++		airtime = vow->tx_airtime;
++		vow->tx_airtime = 0;
++		spin_unlock_bh(&vow->lock);
++
++		seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\tTxAirtime: %llu\n",
++		           sta->addr, i, vif->band_idx, vif->omac_idx, airtime);
++	}
++	rcu_read_unlock();
++
++	return 0;
++}
++
+ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -889,6 +973,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
+ 				    mt7996_twt_stats);
+ 	debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "vow_info", dir,
++	                            mt7996_vow_info_read);
++	debugfs_create_file("atf_enable", 0600, dir, phy, &fops_atf_enable);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "airtime", dir,
++	                            mt7996_airtime_read);
+ 
+ 	if (phy->mt76->cap.has_5ghz) {
+ 		debugfs_create_u32("dfs_hw_pattern", 0400, dir,
 diff --git a/mt7996/init.c b/mt7996/init.c
-index d539af0..d1db1d7 100644
+index d807c357..50453801 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -553,6 +553,37 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
+@@ -566,6 +566,37 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
  	return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
  }
  
@@ -53,7 +161,7 @@
  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,
+@@ -638,6 +669,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
  	if (ret)
  		goto error;
  
@@ -66,7 +174,7 @@
  	ret = mt7996_init_debugfs(phy);
  	if (ret)
  		goto error;
-@@ -1315,6 +1352,12 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1443,6 +1480,12 @@ int mt7996_register_device(struct mt7996_dev *dev)
  
  	dev->recovery.hw_init_done = true;
  
@@ -79,11 +187,42 @@
  	ret = mt7996_init_debugfs(&dev->phy);
  	if (ret)
  		goto error;
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index a9d8f7dd..d51f4129 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -103,6 +103,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ 	};
+ 	struct ieee80211_sta *sta;
+ 	struct mt7996_sta *msta;
++	struct mt7996_vow_sta_ctrl *vow;
+ 	u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
+ 	LIST_HEAD(sta_poll_list);
+ 	int i;
+@@ -161,6 +162,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ 
+ 		sta = container_of((void *)msta, struct ieee80211_sta,
+ 				   drv_priv);
++		vow = &msta->vow;
+ 		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ 			u8 q = mt76_connac_lmac_mapping(i);
+ 			u32 tx_cur = tx_time[q];
+@@ -171,6 +173,10 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+ 				continue;
+ 
+ 			ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
++
++			spin_lock_bh(&vow->lock);
++			vow->tx_airtime += tx_cur;
++			spin_unlock_bh(&vow->lock);
+ 		}
+ 
+ 		/* get signal strength of resp frames (CTS/BA/ACK) */
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index b2cb627..1915a22 100644
+index 3116e664..45a44cd8 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,
+@@ -2220,34 +2220,37 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  }
  
  static int
@@ -126,6 +265,8 @@
 +	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;
++	vow->tx_airtime = 0;
++	spin_lock_init(&vow->lock);
 +
 +	ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
 +	if (ret)
@@ -143,7 +284,7 @@
  }
  
  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,
+@@ -2301,7 +2304,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  		mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
  	}
  
@@ -152,8 +293,8 @@
  	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);
+@@ -5137,6 +5140,218 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+ 				 &req, sizeof(req), false);
  }
  
 +int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
@@ -372,10 +513,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 0aa68f7..fb81645 100644
+index a2604192..7b8540f6 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -860,6 +860,7 @@ enum {
+@@ -964,6 +964,7 @@ enum {
  
  enum {
  	UNI_VOW_DRR_CTRL,
@@ -384,10 +525,10 @@
  	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
+index e6a0b15a..56538825 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -107,6 +107,12 @@
+@@ -115,6 +115,12 @@
  #define MT7996_RX_MSDU_PAGE_SIZE	(128 + \
  					 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
  
@@ -400,9 +541,9 @@
  struct mt7996_vif;
  struct mt7996_sta;
  struct mt7996_dfs_pulse;
-@@ -187,6 +193,79 @@ struct mt7996_twt_flow {
- 
- DECLARE_EWMA(avg_signal, 10, 8)
+@@ -216,6 +222,81 @@ enum mt7996_dpd_ch_num {
+ 	DPD_CH_NUM_TYPE_MAX,
+ };
  
 +enum {
 +	VOW_SEARCH_AC_FIRST,
@@ -475,12 +616,14 @@
 +	bool paused;
 +	u8 bss_grp_idx;
 +	u8 drr_quantum[IEEE80211_NUM_ACS];
++	u64 tx_airtime;
++	spinlock_t lock;
 +};
 +
  struct mt7996_sta {
  	struct mt76_wcid wcid; /* must be first */
  
-@@ -206,6 +285,8 @@ struct mt7996_sta {
+@@ -235,6 +316,8 @@ struct mt7996_sta {
  		u8 flowid_mask;
  		struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
  	} twt;
@@ -489,7 +632,7 @@
  };
  
  struct mt7996_vif {
-@@ -470,6 +551,7 @@ struct mt7996_dev {
+@@ -492,6 +575,7 @@ struct mt7996_dev {
  
  	u8 wtbl_size_group;
  
@@ -497,18 +640,21 @@
  #ifdef CONFIG_MTK_DEBUG
  	u16 wlan_idx;
  	struct {
-@@ -697,6 +779,10 @@ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+@@ -712,10 +796,12 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
+ #ifdef CONFIG_NL80211_TESTMODE
  void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
  #endif
- 
+-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);
+ int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable);
 +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)
+ 
+ static inline u8 mt7996_max_interface_num(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)
+@@ -765,6 +851,14 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
  	return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
  }
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch
deleted file mode 100644
index fec02ea..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2011-wifi-mt76-mt7996-add-dma-mask-limitation.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-mtk-wifi-mt76-mt7996-wed-add-SER0.5-support-w-wed3.0.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-mtk-wifi-mt76-mt7996-wed-add-SER0.5-support-w-wed3.0.patch
new file mode 100644
index 0000000..d78fcf3
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2012-mtk-wifi-mt76-mt7996-wed-add-SER0.5-support-w-wed3.0.patch
@@ -0,0 +1,386 @@
+From 2e7ac514e17ad740c9a837190f9d43ebeb8a9397 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 12 Oct 2023 10:04:54 +0800
+Subject: [PATCH 2012/2020] mtk: wifi: mt76: mt7996: wed: add SER0.5 support w/
+ wed3.0
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c           |  13 ++---
+ dma.h           |   2 +-
+ mt76.h          |  14 ++++--
+ mt792x_dma.c    |   6 +--
+ mt7996/dma.c    |  20 ++++++--
+ mt7996/init.c   | 127 +++++++++++++++++++++++++++++++-----------------
+ mt7996/mac.c    |  25 ++++++++++
+ mt7996/mt7996.h |   1 +
+ 8 files changed, 145 insertions(+), 63 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 5bff27dd..5ddb6be9 100644
+--- a/dma.c
++++ b/dma.c
+@@ -220,9 +220,9 @@ __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
+ }
+ 
+ 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)
+ {
+-	__mt76_dma_queue_reset(dev, q, true);
++	__mt76_dma_queue_reset(dev, q, reset);
+ }
+ 
+ static int
+@@ -542,7 +542,8 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+ 	if (!q->queued)
+ 		return NULL;
+ 
+-	if (mt76_queue_is_wed_rro_data(q))
++	if (mt76_queue_is_wed_rro_data(q) ||
++	    mt76_queue_is_wed_rro_msdu_pg(q))
+ 		return NULL;
+ 
+ 	if (!mt76_queue_is_wed_rro_ind(q)) {
+@@ -772,7 +773,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, true);
+ 		mt76_dma_rx_fill(dev, q);
+ 
+ 		ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
+@@ -801,7 +802,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ 		break;
+ 	case MT76_WED_RRO_Q_IND:
+ 		q->flags &= ~MT_QFLAG_WED;
+-		mt76_dma_queue_reset(dev, q);
++		mt76_dma_queue_reset(dev, q, true);
+ 		mt76_dma_rx_fill(dev, q);
+ 		mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
+ 		break;
+@@ -868,7 +869,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ 			return 0;
+ 	}
+ 
+-	mt76_dma_queue_reset(dev, q);
++	mt76_dma_queue_reset(dev, q, true);
+ 
+ 	return 0;
+ }
+diff --git a/dma.h b/dma.h
+index c479cc63..b7e63bd5 100644
+--- a/dma.h
++++ b/dma.h
+@@ -85,7 +85,7 @@ void mt76_dma_wed_reset(struct mt76_dev *dev);
+ static inline void
+ mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+-	dev->queue_ops->reset_q(dev, q);
++	dev->queue_ops->reset_q(dev, q, true);
+ 	if (mtk_wed_device_active(&dev->mmio.wed))
+ 		mt76_dma_wed_setup(dev, q, true);
+ }
+diff --git a/mt76.h b/mt76.h
+index 2ce1e84e..cf88eafa 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -295,7 +295,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 reset);
+ };
+ 
+ enum mt76_phy_type {
+@@ -1722,8 +1722,13 @@ static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
+ 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);
++	       (FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA);
++}
++
++static inline bool mt76_queue_is_wed_rro_msdu_pg(struct mt76_queue *q)
++{
++	return mt76_queue_is_wed_rro(q) &&
++	       (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)
+@@ -1732,7 +1737,8 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
+ 		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);
++	       mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q) ||
++	       mt76_queue_is_wed_rro_msdu_pg(q);
+ 
+ }
+ 
+diff --git a/mt792x_dma.c b/mt792x_dma.c
+index 488326ce..8811351c 100644
+--- a/mt792x_dma.c
++++ b/mt792x_dma.c
+@@ -172,13 +172,13 @@ mt792x_dma_reset(struct mt792x_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], true);
+ 
+ 	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], true);
+ 
+ 	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], true);
+ 
+ 	mt76_tx_status_check(&dev->mt76, true);
+ 
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 40ab65f8..8df119d0 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -710,21 +710,31 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+ 	}
+ 
+ 	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], true);
+ 
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
+-		if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+ 			if (mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]) ||
+-			    mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
++			    mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i])) {
++				if (force && mt76_queue_is_wed_rro_data(&dev->mt76.q_rx[i]))
++					mt76_queue_reset(dev, &dev->mt76.q_rx[i], false);
+ 				continue;
++			}
++		}
+ 
+-		mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
++		mt76_queue_reset(dev, &dev->mt76.q_rx[i], true);
+ 	}
+ 
+ 	mt76_tx_status_check(&dev->mt76, true);
+ 
+-	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) && force &&
++		    (mt76_queue_is_wed_rro_ind(&dev->mt76.q_rx[i]) ||
++		     mt76_queue_is_wed_rro_msdu_pg(&dev->mt76.q_rx[i])))
++			continue;
++
+ 		mt76_queue_rx_reset(dev, i);
++	}
+ 
+ 	mt7996_dma_enable(dev, !force);
+ }
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 50453801..a1b76e33 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -728,11 +728,91 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
+ 	msleep(20);
+ }
+ 
+-static int mt7996_wed_rro_init(struct mt7996_dev *dev)
++void mt7996_rro_hw_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;
++	int i;
++
++	if (!dev->has_rro)
++		return;
++
++	if (is_mt7992(&dev->mt76)) {
++		/* set emul 3.0 function */
++		mt76_wr(dev, MT_RRO_3_0_EMU_CONF,
++			MT_RRO_3_0_EMU_CONF_EN_MASK);
++
++		mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,
++			dev->wed_rro.addr_elem[0].phy_addr);
++	} else {
++		/* 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;
++	if (is_mt7996(&dev->mt76))
++		wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
++	else
++		wed->wlan.ind_cmd.particular_sid = 1;
++	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);
++
++	if (is_mt7992(&dev->mt76)) {
++		reg = MT_RRO_MSDU_PG_SEG_ADDR0;
++
++		mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG,
++			 MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN);
++
++		/* setup Msdu page address */
++		for (i = 0; i < MT7996_RRO_MSDU_PG_CR_CNT; i++) {
++			mt76_wr(dev, reg, dev->wed_rro.msdu_pg[i].phy_addr >> 4);
++			reg += 4;
++		}
++		mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
++			MT_RRO_PARTICULAR_CONFG_EN |
++			FIELD_PREP(MT_RRO_PARTICULAR_SID, 1));
++	} else {
++		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);
++#endif
++}
++
++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;
+ 	struct mt7996_wed_rro_addr *addr;
+ 	void *ptr;
+ 	int i;
+@@ -792,50 +872,9 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
+ 		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 */
++	mt7996_rro_hw_init(dev);
++
+ 	return mt7996_dma_rro_init(dev);
+ #else
+ 	return 0;
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index d51f4129..19e66256 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1755,6 +1755,31 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+ 	if (ret)
+ 		goto out;
+ 
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->has_rro) {
++		u32 wed_irq_mask = dev->mt76.mmio.irqmask |
++				   MT_INT_RRO_RX_DONE |
++				   MT_INT_TX_DONE_BAND2;
++
++		mt7996_rro_hw_init(dev);
++		mt76_for_each_q_rx(&dev->mt76, i) {
++			if (mt76_queue_is_wed_rro_ind(&dev->mt76.q_rx[i]) ||
++			    mt76_queue_is_wed_rro_msdu_pg(&dev->mt76.q_rx[i]))
++				mt76_queue_rx_reset(dev, i);
++		}
++
++		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
++		mtk_wed_device_start_hwrro(&dev->mt76.mmio.wed, wed_irq_mask, false);
++		mt7996_irq_enable(dev, wed_irq_mask);
++		mt7996_irq_disable(dev, 0);
++	}
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) {
++		mt76_wr(dev, MT_INT_PCIE1_MASK_CSR,
++			MT_INT_TX_RX_DONE_EXT);
++		mtk_wed_device_start(&dev->mt76.mmio.wed_hif2,
++				     MT_INT_TX_RX_DONE_EXT);
++	}
++
+ 	/* set the necessary init items */
+ 	ret = mt7996_mcu_set_eeprom(dev);
+ 	if (ret)
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 56538825..7a1cae71 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -691,6 +691,7 @@ extern const struct mt76_testmode_ops mt7996_testmode_ops;
+ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
+ 				     void __iomem *mem_base, u32 device_id);
+ void mt7996_wfsys_reset(struct mt7996_dev *dev);
++void mt7996_rro_hw_init(struct mt7996_dev *dev);
+ 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);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-mtk-wifi-mt76-mt7996-support-backaward-compatiable.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-mtk-wifi-mt76-mt7996-support-backaward-compatiable.patch
new file mode 100644
index 0000000..671d734
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-mtk-wifi-mt76-mt7996-support-backaward-compatiable.patch
@@ -0,0 +1,223 @@
+From 68d3bbf7120da35068e5983d89cae5ee470e55f4 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Fri, 6 Oct 2023 20:59:42 +0800
+Subject: [PATCH 2013/2020] mtk: wifi: mt76: mt7996: support backaward
+ compatiable
+
+revert upstream wed trigger mode to polling mode
+
+Signed-off-by: mtk27745 <rex.lu@mediatek.com>
+
+[Description]
+Change the SW token size from 1024 to 15360 according to HW capability.
+
+[Release-log]
+N/A
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mmio.c          |  2 +-
+ mt7996/dma.c    |  2 +-
+ mt7996/mac.c    |  2 +-
+ mt7996/main.c   |  6 +++---
+ mt7996/mcu.c    |  2 +-
+ mt7996/mmio.c   | 20 +++++++++++---------
+ mt7996/mt7996.h |  1 +
+ mt7996/pci.c    | 17 +++++++++--------
+ 8 files changed, 28 insertions(+), 24 deletions(-)
+
+diff --git a/mmio.c b/mmio.c
+index 269fd932..117da4d1 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 8df119d0..773bab71 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -431,7 +431,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/mac.c b/mt7996/mac.c
+index 19e66256..8171a43d 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1998,7 +1998,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 
+ 		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
+ 
+-		mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, wed_irq_mask,
++		mtk_wed_device_start_hwrro(&dev->mt76.mmio.wed, wed_irq_mask,
+ 					    true);
+ 		mt7996_irq_enable(dev, wed_irq_mask);
+ 		mt7996_irq_disable(dev, 0);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 939b0943..45461949 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1593,10 +1593,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
+ 	path->mtk_wdma.wcid = msta->wcid.idx;
+ 
+ 	if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU) &&
+-	    mtk_wed_is_amsdu_supported(wed))
+-		path->mtk_wdma.amsdu = msta->wcid.amsdu;
++	    mtk_wed_device_support_pao(wed))
++		path->mtk_wdma.amsdu_en = msta->wcid.amsdu;
+ 	else
+-		path->mtk_wdma.amsdu = 0;
++		path->mtk_wdma.amsdu_en = 0;
+ 
+ 	ctx->dev = NULL;
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 45a44cd8..57af55ec 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3247,7 +3247,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 488f5103..69d16dad 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[] = {
+@@ -352,14 +352,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) +
+@@ -367,7 +367,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;
+ 
+@@ -409,11 +409,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;
+@@ -431,6 +431,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 7a1cae71..056d07fe 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -74,6 +74,7 @@
+ #define MT7996_EEPROM_BLOCK_SIZE	16
+ #define MT7996_TOKEN_SIZE		16384
+ #define MT7996_HW_TOKEN_SIZE		8192
++#define MT7996_SW_TOKEN_SIZE		15360
+ 
+ #define MT7996_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */
+ #define MT7996_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 05830c01..4e957771 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -171,7 +171,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 
+ 		ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
+ 		if (ret < 0)
+-			goto free_hif2_wed_irq_vector;
++			goto free_wed_or_irq_vector;
+ 
+ 		if (!ret) {
+ 			ret = pci_alloc_irq_vectors(hif2_dev, 1, 1,
+@@ -180,14 +180,15 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 				goto free_hif2;
+ 
+ 			dev->hif2->irq = hif2_dev->irq;
+-			hif2_irq = dev->hif2->irq;
++		} else {
++			dev->hif2->irq = irq;
+ 		}
+ 
+-		ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler,
+-				       IRQF_SHARED, KBUILD_MODNAME "-hif",
+-				       dev);
++		ret = devm_request_irq(mdev->dev, dev->hif2->irq,
++				       mt7996_irq_handler, IRQF_SHARED,
++				       KBUILD_MODNAME "-hif", dev);
+ 		if (ret)
+-			goto free_hif2_wed_irq_vector;
++			goto free_hif2_irq_vector;
+ 
+ 		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ 		/* master switch of PCIe tnterrupt enable */
+@@ -202,8 +203,8 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 
+ free_hif2_irq:
+ 	if (dev->hif2)
+-		devm_free_irq(mdev->dev, hif2_irq, dev);
+-free_hif2_wed_irq_vector:
++		devm_free_irq(mdev->dev, dev->hif2->irq, dev);
++free_hif2_irq_vector:
+ 	if (dev->hif2) {
+ 		if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
+ 			mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch
deleted file mode 100644
index 8dd2d61..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2013-wifi-mt76-mt7996-support-TX-RX-for-Kite-without-WED-.patch
+++ /dev/null
@@ -1,234 +0,0 @@
-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/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-mtk-wifi-mt76-mt7996-wed-add-wed-support-for-mt7992.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-mtk-wifi-mt76-mt7996-wed-add-wed-support-for-mt7992.patch
new file mode 100644
index 0000000..1b52408
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2014-mtk-wifi-mt76-mt7996-wed-add-wed-support-for-mt7992.patch
@@ -0,0 +1,432 @@
+From fe2c7b5514551f1b61404e9bc11cea12c6ae77de Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Fri, 8 Sep 2023 11:57:39 +0800
+Subject: [PATCH 2014/2020] mtk: wifi: mt76: mt7996: wed: add wed support for
+ mt7992
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+
+Fix incomplete WED initialization for Kite band-1 RX ring.
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt7996/dma.c    | 91 +++++++++++++++++++++++++++++++++----------------
+ mt7996/init.c   | 12 +++++++
+ mt7996/mac.c    |  4 +++
+ mt7996/mmio.c   | 49 ++++++++++++++++++--------
+ mt7996/mt7996.h | 10 +++++-
+ mt7996/pci.c    | 10 ++++--
+ mt7996/regs.h   | 14 +++++++-
+ 7 files changed, 142 insertions(+), 48 deletions(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 773bab71..4c92f13b 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -77,18 +77,23 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+ 			   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);
++		if (is_mt7996(&dev->mt76)) {
++			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);
++		} else {
++			RXQ_CONFIG(MT_RXQ_RRO_BAND1, WFDMA0, MT_INT_RX_DONE_RRO_BAND1,
++				   MT7996_RXQ_RRO_BAND1);
++		}
+ 
+ 		RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
+ 			   MT7996_RXQ_RRO_IND);
+@@ -146,8 +151,13 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
+ 	if (dev->has_rro) {
+ 		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));
++		if (is_mt7996(&dev->mt76))
++			mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
++				PREFETCH(0x10));
++		else
++			mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND1) + 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,
+@@ -360,12 +370,16 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 		 * so, redirect pcie0 rx ring3 interrupt to pcie1
+ 		 */
+ 		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+-		    dev->has_rro)
++		    dev->has_rro) {
++			u32 intr = is_mt7996(&dev->mt76) ?
++				   MT_WFDMA0_RX_INT_SEL_RING6 :
++				   MT_WFDMA0_RX_INT_SEL_RING9;
+ 			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
+-				 MT_WFDMA0_RX_INT_SEL_RING6);
+-		else
++				 intr);
++		} else {
+ 			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
+ 				 MT_WFDMA0_RX_INT_SEL_RING3);
++		}
+ 	}
+ 
+ 	mt7996_dma_start(dev, reset, true);
+@@ -400,7 +414,7 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	if (mt7996_band_valid(dev, MT_BAND1)) {
++	if (mt7996_band_valid(dev, MT_BAND1) && is_mt7996(&dev->mt76)) {
+ 		/* 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;
+@@ -521,7 +535,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->has_rro) {
++	if (mtk_wed_device_active(wed) &&
++	    ((is_mt7996(&dev->mt76) && !dev->has_rro) ||
++	     (is_mt7992(&dev->mt76)))) {
+ 		dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
+ 		dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
+ 	}
+@@ -567,6 +583,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	} 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;
++		if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
++			dev->mt76.q_rx[MT_RXQ_BAND1].flags = MT_WED_Q_RX(1);
++			dev->mt76.q_rx[MT_RXQ_BAND1].wed = wed;
++		}
++
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
+ 				       MT_RXQ_ID(MT_RXQ_BAND1),
+ 				       MT7996_RX_RING_SIZE,
+@@ -600,17 +621,29 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 		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;
++		if (is_mt7992(&dev->mt76)) {
++			dev->mt76.q_rx[MT_RXQ_RRO_BAND1].flags =
++				MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
++			dev->mt76.q_rx[MT_RXQ_RRO_BAND1].wed = wed;
++			ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1],
++					       MT_RXQ_ID(MT_RXQ_RRO_BAND1),
++					       MT7996_RX_RING_SIZE,
++					       MT7996_RX_BUF_SIZE,
++					       MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1));
++			if (ret)
++				return ret;
++		} else {
++			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;
++			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 */
+diff --git a/mt7996/init.c b/mt7996/init.c
+index a1b76e33..cc7d570a 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -806,6 +806,7 @@ void mt7996_rro_hw_init(struct mt7996_dev *dev)
+ 	/* interrupt enable */
+ 	mt76_wr(dev, MT_RRO_HOST_INT_ENA,
+ 		MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
++
+ #endif
+ }
+ 
+@@ -858,6 +859,17 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
+ 			dev->wed_rro.addr_elem[i].phy_addr;
+ 	}
+ 
++	for (i = 0; i < MT7996_RRO_MSDU_PG_CR_CNT; i++) {
++		ptr = dmam_alloc_coherent(dev->mt76.dma_dev, MT7996_RRO_MSDU_PG_SIZE_PER_CR,
++					  &dev->wed_rro.msdu_pg[i].phy_addr,
++					  GFP_KERNEL);
++		if (!ptr)
++			return -ENOMEM;
++		dev->wed_rro.msdu_pg[i].ptr = ptr;
++
++		memset(dev->wed_rro.msdu_pg[i].ptr, 0, MT7996_RRO_MSDU_PG_SIZE_PER_CR);
++	}
++
+ 	ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
+ 				  MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
+ 				  &dev->wed_rro.session.phy_addr,
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 8171a43d..751a960a 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1998,6 +1998,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 
+ 		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
+ 
++		if (is_mt7992(&dev->mt76) && dev->has_rro)
++			mt76_wr(dev, MT_RRO_3_0_EMU_CONF,
++				MT_RRO_3_0_EMU_CONF_EN_MASK);
++
+ 		mtk_wed_device_start_hwrro(&dev->mt76.mmio.wed, wed_irq_mask,
+ 					    true);
+ 		mt7996_irq_enable(dev, wed_irq_mask);
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 69d16dad..b5b97dcb 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -318,7 +318,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 
+ 	dev->has_rro = true;
+ 
+-	hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++	if (dev->hif2)
++		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+ 
+ 	if (hif2)
+ 		wed = &dev->mt76.mmio.wed_hif2;
+@@ -353,8 +354,8 @@ 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[0] = wed->wlan.phy_base + hif1_ofs +
+-				     MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
+-				     MT7996_RXQ_BAND0 * MT_RING_SIZE;
++				     MT_RXQ_RING_BASE(MT7996_RXQ_BAND2) +
++				     MT7996_RXQ_BAND2 * MT_RING_SIZE;
+ 
+ 		wed->wlan.chip_id = 0x7991;
+ 		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
+@@ -374,9 +375,19 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 		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;
++		if (is_mt7996(&dev->mt76)) {
++			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;
++		} else {
++			wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base +
++						    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND1) +
++						    MT7996_RXQ_RRO_BAND1 * MT_RING_SIZE;
++			wed->wlan.wpdma_rx[1] = wed->wlan.phy_base +
++						MT_RXQ_RING_BASE(MT7996_RXQ_BAND1) +
++						MT7996_RXQ_BAND1 * 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;
+@@ -386,10 +397,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 		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;
++		if (is_mt7996(&dev->mt76)) {
++			wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
++			wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
++		} else {
++			wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND1) - 1;
++			wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND1) - 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;
+@@ -397,14 +412,20 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 
+ 		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;
++		if (is_mt7996(&dev->mt76)) {
++			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;
++			}
+ 		} 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;
++						 MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
+ 		}
+ 		dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
+ 	}
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 056d07fe..677f00b0 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -122,6 +122,10 @@
+ #define MT7996_DRR_STA_AC2_QNTM_MASK	GENMASK(18, 16)
+ #define MT7996_DRR_STA_AC3_QNTM_MASK	GENMASK(22, 20)
+ 
++/* RRO 3.1 */
++#define MT7996_RRO_MSDU_PG_CR_CNT 8
++#define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -181,7 +185,7 @@ enum mt7996_rxq_id {
+ 	MT7996_RXQ_BAND1 = 5, /* for mt7992 */
+ 	MT7996_RXQ_BAND2 = 5,
+ 	MT7996_RXQ_RRO_BAND0 = 8,
+-	MT7996_RXQ_RRO_BAND1 = 8,/* unused */
++	MT7996_RXQ_RRO_BAND1 = 9,
+ 	MT7996_RXQ_RRO_BAND2 = 6,
+ 	MT7996_RXQ_MSDU_PG_BAND0 = 10,
+ 	MT7996_RXQ_MSDU_PG_BAND1 = 11,
+@@ -540,6 +544,10 @@ struct mt7996_dev {
+ 			void *ptr;
+ 			dma_addr_t phy_addr;
+ 		} session;
++		struct {
++			void *ptr;
++			dma_addr_t phy_addr;
++		} msdu_pg[MT7996_RRO_MSDU_PG_CR_CNT];
+ 
+ 		struct work_struct work;
+ 		struct list_head poll_list;
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 4e957771..f0d3f199 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -107,7 +107,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 	struct pci_dev *hif2_dev;
+ 	struct mt7996_hif *hif2;
+ 	struct mt7996_dev *dev;
+-	int irq, hif2_irq, ret;
++	int irq, ret;
+ 	struct mt76_dev *mdev;
+ 
+ 	hif2_enable |= (id->device == 0x7990 || id->device == 0x7991);
+@@ -143,6 +143,8 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 	mdev = &dev->mt76;
+ 	mt7996_wfsys_reset(dev);
+ 	hif2 = mt7996_pci_init_hif2(pdev);
++	if (hif2)
++		dev->hif2 = hif2;
+ 
+ 	ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
+ 	if (ret < 0)
+@@ -167,9 +169,11 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 
+ 	if (hif2) {
+ 		hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
+-		dev->hif2 = hif2;
++		ret = 0;
++
++		if (is_mt7996(&dev->mt76))
++			ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &irq);
+ 
+-		ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
+ 		if (ret < 0)
+ 			goto free_wed_or_irq_vector;
+ 
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 8d1462a7..352d1b29 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -77,6 +77,8 @@ enum offs_rev {
+ #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_BASE0			MT_RRO_TOP(0x30)
+ #define MT_RRO_ADDR_ARRAY_BASE1			MT_RRO_TOP(0x34)
+ #define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE	BIT(31)
+ 
+@@ -97,6 +99,14 @@ enum offs_rev {
+ 
+ #define MT_RRO_ADDR_ELEM_SEG_ADDR0		MT_RRO_TOP(0x400)
+ 
++#define MT_RRO_3_0_EMU_CONF			MT_RRO_TOP(0x600)
++#define MT_RRO_3_0_EMU_CONF_EN_MASK		BIT(11)
++
++#define MT_RRO_3_1_GLOBAL_CONFIG		MT_RRO_TOP(0x604)
++#define MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN	BIT(0)
++
++#define MT_RRO_MSDU_PG_SEG_ADDR0		MT_RRO_TOP(0x620)
++
+ #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)
+@@ -402,6 +412,7 @@ enum offs_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_RX_INT_SEL_RING9		BIT(9)
+ 
+ #define MT_WFDMA0_MCU_HOST_INT_ENA		MT_WFDMA0(0x1f4)
+ 
+@@ -503,13 +514,14 @@ enum offs_rev {
+ #define MT_INT_RX_DONE_WA_EXT			BIT(3) /* for mt7992 */
+ #define MT_INT_RX_DONE_WA_TRI			BIT(3)
+ #define MT_INT_RX_TXFREE_MAIN			BIT(17)
++#define MT_INT_RX_TXFREE_BAND1			BIT(15)
+ #define MT_INT_RX_TXFREE_TRI			BIT(15)
+ #define MT_INT_RX_DONE_BAND2_EXT		BIT(23)
+ #define MT_INT_RX_TXFREE_EXT			BIT(26)
+ #define MT_INT_MCU_CMD				BIT(29)
+ 
+ #define MT_INT_RX_DONE_RRO_BAND0		BIT(16)
+-#define MT_INT_RX_DONE_RRO_BAND1		BIT(16)
++#define MT_INT_RX_DONE_RRO_BAND1		BIT(17)
+ #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)
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2015-mtk-wifi-mt76-mt7992-wed-add-2pcie-one-wed-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2015-mtk-wifi-mt76-mt7992-wed-add-2pcie-one-wed-support.patch
new file mode 100644
index 0000000..21d53cc
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2015-mtk-wifi-mt76-mt7992-wed-add-2pcie-one-wed-support.patch
@@ -0,0 +1,177 @@
+From fe7511e18f6fd543b5b3d2fac9dd61c9ed02d938 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Wed, 13 Sep 2023 17:35:43 +0800
+Subject: [PATCH 2015/2020] mtk: wifi: mt76: mt7992: wed: add 2pcie one wed
+ support
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt7996/dma.c         | 13 +++++++++++--
+ mt7996/mmio.c        |  7 +++----
+ mt7996/mtk_debug.h   |  5 +++++
+ mt7996/mtk_debugfs.c | 25 ++++++++++++++++++-------
+ mt7996/regs.h        |  2 ++
+ 5 files changed, 39 insertions(+), 13 deletions(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 4c92f13b..80458b31 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -354,6 +354,13 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 			 MT_WFDMA_HOST_CONFIG_PDMA_BAND |
+ 			 MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
+ 
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    is_mt7992(&dev->mt76)) {
++			mt76_set(dev, MT_WFDMA_HOST_CONFIG,
++				 MT_WFDMA_HOST_CONFIG_PDMA_BAND |
++				 MT_WFDMA_HOST_CONFIG_BAND1_PCIE1);
++		}
++
+ 		/* AXI read outstanding number */
+ 		mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
+ 			 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
+@@ -373,7 +380,8 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 		    dev->has_rro) {
+ 			u32 intr = is_mt7996(&dev->mt76) ?
+ 				   MT_WFDMA0_RX_INT_SEL_RING6 :
+-				   MT_WFDMA0_RX_INT_SEL_RING9;
++				   MT_WFDMA0_RX_INT_SEL_RING9 |
++				   MT_WFDMA0_RX_INT_SEL_RING5;
+ 			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
+ 				 intr);
+ 		} else {
+@@ -629,10 +637,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 					       MT_RXQ_ID(MT_RXQ_RRO_BAND1),
+ 					       MT7996_RX_RING_SIZE,
+ 					       MT7996_RX_BUF_SIZE,
+-					       MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1));
++					       MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + hif1_ofs);
+ 			if (ret)
+ 				return ret;
+ 		} else {
++			/* 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;
+ 
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index b5b97dcb..8faceb3b 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -380,10 +380,10 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 						    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
+ 						    MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
+ 		} else {
+-			wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base +
++			wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
+ 						    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND1) +
+ 						    MT7996_RXQ_RRO_BAND1 * MT_RING_SIZE;
+-			wed->wlan.wpdma_rx[1] = wed->wlan.phy_base +
++			wed->wlan.wpdma_rx[1] = wed->wlan.phy_base + hif1_ofs +
+ 						MT_RXQ_RING_BASE(MT7996_RXQ_BAND1) +
+ 						MT7996_RXQ_BAND1 * MT_RING_SIZE;
+ 		}
+@@ -521,10 +521,9 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
+ 		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)) {
++			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);
+diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
+index 27d8f1cb..da2a6072 100644
+--- a/mt7996/mtk_debug.h
++++ b/mt7996/mtk_debug.h
+@@ -561,6 +561,11 @@ struct queue_desc {
+ #define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL1_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x574) // 8574
+ #define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL2_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x578) // 8578
+ #define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL3_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x57c) // 857C
++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING9_CTRL0_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x590) // 8590
++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING9_CTRL1_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x594) // 8594
++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING9_CTRL2_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x598) // 8598
++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING9_CTRL3_ADDR     (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x59c) // 859C
++
+ //MCU DMA
+ //#define WF_WFDMA_MCU_DMA0_BASE                                 0x02000
+ #define WF_WFDMA_MCU_DMA0_BASE                                 0x54000000
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 9cf3e6dc..c1764824 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -536,14 +536,22 @@ mt7996_show_dma_info(struct seq_file *s, struct mt7996_dev *dev)
+ 		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR);
+ 	dump_dma_rx_ring_info(s, dev, "R5:Data1(MAC2H)", "Both",
+ 		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR);
+-	dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both",
+-		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR);
++	if (is_mt7996(&dev->mt76))
++		dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both",
++			WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR);
++	else
++		dump_dma_rx_ring_info(s, dev, "R6:TxDone0(MAC2H)", "Both",
++			WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR);
+ 	dump_dma_rx_ring_info(s, dev, "R7:TxDone1(MAC2H)", "Both",
+ 		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR);
+ 	dump_dma_rx_ring_info(s, dev, "R8:BUF0(MAC2H)", "Both",
+ 		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL0_ADDR);
+-	dump_dma_rx_ring_info(s, dev, "R9:TxDone0(MAC2H)", "Both",
+-		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL0_ADDR);
++	if (is_mt7996(&dev->mt76))
++		dump_dma_rx_ring_info(s, dev, "R9:TxDone0(MAC2H)", "Both",
++			WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL0_ADDR);
++	else
++		dump_dma_rx_ring_info(s, dev, "R9:BUF0(MAC2H)", "Both",
++			WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL0_ADDR);
+ 	dump_dma_rx_ring_info(s, dev, "R10:MSDU_PG0(MAC2H)", "Both",
+ 		WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL0_ADDR);
+ 	dump_dma_rx_ring_info(s, dev, "R11:MSDU_PG1(MAC2H)", "Both",
+@@ -561,15 +569,18 @@ mt7996_show_dma_info(struct seq_file *s, struct mt7996_dev *dev)
+ 			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL0_ADDR);
+ 		dump_dma_tx_ring_info(s, dev, "T22:TXD?(H2WA)", "AP",
+ 			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL0_ADDR);
+-
+ 		dump_dma_rx_ring_info(s, dev, "R3:TxDone1(WA2H)", "AP",
+ 			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL0_ADDR);
+ 		dump_dma_rx_ring_info(s, dev, "R5:Data1(MAC2H)", "Both",
+ 			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL0_ADDR);
+-		dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both",
+-			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL0_ADDR);
++		if (is_mt7996(&dev->mt76))
++			dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both",
++				WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL0_ADDR);
+ 		dump_dma_rx_ring_info(s, dev, "R7:TxDone1(MAC2H)", "Both",
+ 			WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL0_ADDR);
++		if (is_mt7992(&dev->mt76))
++			dump_dma_rx_ring_info(s, dev, "R9:BUF1(MAC2H)", "Both",
++				WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING9_CTRL0_ADDR);
+ 	}
+ 
+ 	/* MCU DMA information */
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 352d1b29..a3b62339 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -411,6 +411,7 @@ enum offs_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_RING5		BIT(5)
+ #define MT_WFDMA0_RX_INT_SEL_RING6		BIT(6)
+ #define MT_WFDMA0_RX_INT_SEL_RING9		BIT(9)
+ 
+@@ -451,6 +452,7 @@ enum offs_rev {
+ 
+ #define MT_WFDMA_HOST_CONFIG			MT_WFDMA_EXT_CSR(0x30)
+ #define MT_WFDMA_HOST_CONFIG_PDMA_BAND		BIT(0)
++#define MT_WFDMA_HOST_CONFIG_BAND1_PCIE1	BIT(21)
+ #define MT_WFDMA_HOST_CONFIG_BAND2_PCIE1	BIT(22)
+ 
+ #define MT_WFDMA_EXT_CSR_HIF_MISC		MT_WFDMA_EXT_CSR(0x44)
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2016-mtk-wifi-mt76-mt7996-add-SER-state-log-for-debug.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2016-mtk-wifi-mt76-mt7996-add-SER-state-log-for-debug.patch
new file mode 100644
index 0000000..093244e
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2016-mtk-wifi-mt76-mt7996-add-SER-state-log-for-debug.patch
@@ -0,0 +1,28 @@
+From f6a8fd2686dbc85ca8a4881258e8bde6b1e06481 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Nov 2023 16:37:23 +0800
+Subject: [PATCH 2016/2020] mtk: wifi: mt76: mt7996: add SER state log for
+ debug.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7996/mac.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 751a960a..5ffc6018 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2158,6 +2158,9 @@ void mt7996_coredump(struct mt7996_dev *dev, u8 state)
+ 
+ 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;
+ 
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2017-mtk-wifi-mt76-mt7996-Remove-wed-rro-ring-add-napi-at.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2017-mtk-wifi-mt76-mt7996-Remove-wed-rro-ring-add-napi-at.patch
new file mode 100644
index 0000000..49cb21a
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2017-mtk-wifi-mt76-mt7996-Remove-wed-rro-ring-add-napi-at.patch
@@ -0,0 +1,31 @@
+From b81245ff66c12f52508f3a2fd22ef2c7cf56cde4 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Mon, 6 Nov 2023 10:16:34 +0800
+Subject: [PATCH 2017/2020] mtk: wifi: mt76: mt7996: Remove wed rro ring add
+ napi at init state
+
+without this patch. rro ring will add napi at initial state. once rro ring add napi, it will have chance to be used by host driver. if host driver accessed the ring data, it will cause some issue.
+
+Signed-off-by: mtk27745 <rex.lu@mediatek.com>
+---
+ dma.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/dma.c b/dma.c
+index 5ddb6be9..698f39c0 100644
+--- a/dma.c
++++ b/dma.c
+@@ -1093,6 +1093,10 @@ mt76_dma_init(struct mt76_dev *dev,
+ 	init_completion(&dev->mmio.wed_reset_complete);
+ 
+ 	mt76_for_each_q_rx(dev, i) {
++		if (mtk_wed_device_active(&dev->mmio.wed) &&
++		    mt76_queue_is_wed_rro(&dev->q_rx[i]))
++			continue;
++
+ 		netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
+ 		mt76_dma_rx_fill(dev, &dev->q_rx[i]);
+ 		napi_enable(&dev->napi[i]);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2018-mtk-wifi-mt76-mt7996-Remove-wed_stop-during-L1-SER.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2018-mtk-wifi-mt76-mt7996-Remove-wed_stop-during-L1-SER.patch
new file mode 100644
index 0000000..5ac595c
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2018-mtk-wifi-mt76-mt7996-Remove-wed_stop-during-L1-SER.patch
@@ -0,0 +1,33 @@
+From 3c31acb1c6a90e33ca0aa60f6f605ccc75d0ac93 Mon Sep 17 00:00:00 2001
+From: Rex Lu <rex.lu@mediatek.com>
+Date: Wed, 29 Nov 2023 13:56:52 +0800
+Subject: [PATCH 2018/2020] mtk: wifi: mt76: mt7996: Remove wed_stop during L1
+ SER
+
+Align logan L1 SER flow. During L1 SER, didn't need to close wed interrupt.
+
+Signed-off-by: Rex Lu <rex.lu@mediatek.com>
+---
+ mt7996/mac.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 5ffc6018..0ebad4ac 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1941,12 +1941,6 @@ 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_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);
+-
+ 	ieee80211_stop_queues(mt76_hw(dev));
+ 	if (phy2)
+ 		ieee80211_stop_queues(phy2->mt76->hw);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2019-mtk-wifi-mt76-mt7996-Refactor-rro-del-ba-command-for.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2019-mtk-wifi-mt76-mt7996-Refactor-rro-del-ba-command-for.patch
new file mode 100644
index 0000000..66b06a8
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2019-mtk-wifi-mt76-mt7996-Refactor-rro-del-ba-command-for.patch
@@ -0,0 +1,85 @@
+From 025d64a4244f872c0e767cbefa8dbeb1af84de39 Mon Sep 17 00:00:00 2001
+From: Rex Lu <rex.lu@mediatek.com>
+Date: Wed, 29 Nov 2023 15:51:04 +0800
+Subject: [PATCH 2019/2020] mtk: wifi: mt76: mt7996: Refactor rro del ba
+ command format
+
+1. remove unused struct
+2. refactor upstream del ba command format
+
+Signed-off-by: Rex Lu <rex.lu@mediatek.com>
+---
+ mt7996/mcu.h | 50 +++-----------------------------------------------
+ 1 file changed, 3 insertions(+), 47 deletions(-)
+
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 7b8540f6..a05dd6a5 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -273,7 +273,9 @@ struct mt7996_mcu_wed_rro_ba_delete_event {
+ 	__le16 len;
+ 
+ 	__le16 session_id;
+-	u8 __rsv2[2];
++	__le16 mld_id;
++	u8 tid;
++	u8 __rsv[3];
+ } __packed;
+ 
+ enum  {
+@@ -298,52 +300,6 @@ 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 {
+-	__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;
+-	__le16 mld_id;
+-	u8 tid;
+-	u8 __rsv[3];
+-} __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,
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2020-mtk-wifi-mt76-mt7996-get-airtime-and-RSSI-via-MCU-co.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2020-mtk-wifi-mt76-mt7996-get-airtime-and-RSSI-via-MCU-co.patch
new file mode 100644
index 0000000..c34671f
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2020-mtk-wifi-mt76-mt7996-get-airtime-and-RSSI-via-MCU-co.patch
@@ -0,0 +1,784 @@
+From 555895ccd2379f4b9d94148f7d67afb4a4d97be4 Mon Sep 17 00:00:00 2001
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Date: Fri, 17 Nov 2023 18:08:06 +0800
+Subject: [PATCH 2020/2020] mtk: wifi: mt76: mt7996: get airtime and RSSI via
+ MCU commands
+
+Direct access to WTBL for airtime and RSSI may cause synchronization issue with FW.
+Moreover, frequent access to WTBL, whenever TX-Free-Done event is received, leads to heavy CPU overheads.
+Therefore, indirect access to WTBL, through FW, with lower frequence is performed.
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+---
+ mt76.h               |  20 +++++
+ mt76_connac_mcu.h    |  14 +++-
+ mt7996/debugfs.c     |  17 ++---
+ mt7996/mac.c         | 145 ++++++-----------------------------
+ mt7996/mcu.c         | 177 +++++++++++++++++++++++++++++++++++++++++--
+ mt7996/mcu.h         |  32 +++++++-
+ mt7996/mt7996.h      |  26 ++++++-
+ mt7996/mtk_debugfs.c |  71 +++++++++++++++++
+ mt7996/regs.h        |   2 +
+ 9 files changed, 361 insertions(+), 143 deletions(-)
+
+diff --git a/mt76.h b/mt76.h
+index cf88eafa..942d9c11 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -324,11 +324,15 @@ struct mt76_sta_stats {
+ 	u32 tx_packets;		/* unit: MSDU */
+ 	u32 tx_retries;
+ 	u32 tx_failed;
++	u32 tx_total_mpdu_cnt;
++	u32 tx_failed_mpdu_cnt;
++	u64 tx_airtime;
+ 	/* WED RX */
+ 	u64 rx_bytes;
+ 	u32 rx_packets;
+ 	u32 rx_errors;
+ 	u32 rx_drops;
++	u64 rx_airtime;
+ };
+ 
+ enum mt76_wcid_flags {
+@@ -1312,6 +1316,22 @@ static inline int mt76_decr(int val, int size)
+ 
+ u8 mt76_ac_to_hwq(u8 ac);
+ 
++static inline u8
++mt76_ac_to_tid(u8 ac)
++{
++	static const u8 ac_to_tid[] = {
++		[IEEE80211_AC_BE] = 0,
++		[IEEE80211_AC_BK] = 1,
++		[IEEE80211_AC_VI] = 4,
++		[IEEE80211_AC_VO] = 6
++	};
++
++	if (WARN_ON(ac >= IEEE80211_NUM_ACS))
++		return 0;
++
++	return ac_to_tid[ac];
++}
++
+ static inline struct ieee80211_txq *
+ mtxq_to_txq(struct mt76_txq *mtxq)
+ {
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 306e7bee..8056911f 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1357,11 +1357,23 @@ enum {
+ 	UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
+ };
+ 
++enum UNI_PER_STA_INFO_TAG {
++	UNI_PER_STA_RSSI,
++	UNI_PER_STA_CONTENTION_RX_RATE,
++	UNI_PER_STA_PER,
++	UNI_PER_STA_SNR,
++	UNI_PER_STA_TX_RATE,
++	UNI_PER_STA_TX_CNT,
++	UNI_PER_STA_TID_SN_GET,
++	UNI_PER_STA_TID_SN_SET,
++	UNI_PER_STA_MAX_NUM
++};
++
+ enum UNI_ALL_STA_INFO_TAG {
+ 	UNI_ALL_STA_TXRX_RATE,
+ 	UNI_ALL_STA_TX_STAT,
+ 	UNI_ALL_STA_TXRX_ADM_STAT,
+-	UNI_ALL_STA_TXRX_AIR_TIME,
++	UNI_ALL_STA_TXRX_AIRTIME,
+ 	UNI_ALL_STA_DATA_TX_RETRY_COUNT,
+ 	UNI_ALL_STA_GI_MODE,
+ 	UNI_ALL_STA_TXRX_MSDU_COUNT,
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 3d514c44..c16099f9 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -914,12 +914,11 @@ mt7996_airtime_read(struct seq_file *s, void *data)
+ {
+ 	struct mt7996_dev *dev = dev_get_drvdata(s->private);
+ 	struct mt76_dev *mdev = &dev->mt76;
+-	struct mt7996_vow_sta_ctrl *vow;
++	struct mt76_sta_stats *stats;
+ 	struct ieee80211_sta *sta;
+ 	struct mt7996_sta *msta;
+ 	struct mt76_wcid *wcid;
+ 	struct mt76_vif *vif;
+-	u64 airtime;
+ 	u16 i;
+ 
+ 	seq_printf(s, "VoW Airtime Information:\n");
+@@ -931,16 +930,16 @@ mt7996_airtime_read(struct seq_file *s, void *data)
+ 
+ 		msta = container_of(wcid, struct mt7996_sta, wcid);
+ 		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
+-		vow = &msta->vow;
+ 		vif = &msta->vif->mt76;
++		stats = &wcid->stats;
+ 
+-		spin_lock_bh(&vow->lock);
+-		airtime = vow->tx_airtime;
+-		vow->tx_airtime = 0;
+-		spin_unlock_bh(&vow->lock);
++		seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\t"
++		              "TxAirtime: %llu\tRxAirtime: %llu\n",
++		              sta->addr, i, vif->band_idx, vif->omac_idx,
++		              stats->tx_airtime, stats->rx_airtime);
+ 
+-		seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\tTxAirtime: %llu\n",
+-		           sta->addr, i, vif->band_idx, vif->omac_idx, airtime);
++		stats->tx_airtime = 0;
++		stats->rx_airtime = 0;
+ 	}
+ 	rcu_read_unlock();
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 0ebad4ac..bdf808fc 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -12,8 +12,6 @@
+ #include "mcu.h"
+ #include "vendor.h"
+ 
+-#define to_rssi(field, rcpi)	((FIELD_GET(field, rcpi) - 220) / 2)
+-
+ static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
+ 	.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
+ 	.radar_pattern = {
+@@ -93,110 +91,6 @@ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw)
+ 	return MT_WTBL_LMAC_OFFS(wcid, dw);
+ }
+ 
+-static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
+-{
+-	static const u8 ac_to_tid[] = {
+-		[IEEE80211_AC_BE] = 0,
+-		[IEEE80211_AC_BK] = 1,
+-		[IEEE80211_AC_VI] = 4,
+-		[IEEE80211_AC_VO] = 6
+-	};
+-	struct ieee80211_sta *sta;
+-	struct mt7996_sta *msta;
+-	struct mt7996_vow_sta_ctrl *vow;
+-	u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
+-	LIST_HEAD(sta_poll_list);
+-	int i;
+-
+-	spin_lock_bh(&dev->mt76.sta_poll_lock);
+-	list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
+-	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-
+-	rcu_read_lock();
+-
+-	while (true) {
+-		bool clear = false;
+-		u32 addr, val;
+-		u16 idx;
+-		s8 rssi[4];
+-
+-		spin_lock_bh(&dev->mt76.sta_poll_lock);
+-		if (list_empty(&sta_poll_list)) {
+-			spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-			break;
+-		}
+-		msta = list_first_entry(&sta_poll_list,
+-					struct mt7996_sta, wcid.poll_list);
+-		list_del_init(&msta->wcid.poll_list);
+-		spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-
+-		idx = msta->wcid.idx;
+-
+-		/* refresh peer's airtime reporting */
+-		addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
+-
+-		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+-			u32 tx_last = msta->airtime_ac[i];
+-			u32 rx_last = msta->airtime_ac[i + 4];
+-
+-			msta->airtime_ac[i] = mt76_rr(dev, addr);
+-			msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
+-
+-			tx_time[i] = msta->airtime_ac[i] - tx_last;
+-			rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
+-
+-			if ((tx_last | rx_last) & BIT(30))
+-				clear = true;
+-
+-			addr += 8;
+-		}
+-
+-		if (clear) {
+-			mt7996_mac_wtbl_update(dev, idx,
+-					       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+-			memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
+-		}
+-
+-		if (!msta->wcid.sta)
+-			continue;
+-
+-		sta = container_of((void *)msta, struct ieee80211_sta,
+-				   drv_priv);
+-		vow = &msta->vow;
+-		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+-			u8 q = mt76_connac_lmac_mapping(i);
+-			u32 tx_cur = tx_time[q];
+-			u32 rx_cur = rx_time[q];
+-			u8 tid = ac_to_tid[i];
+-
+-			if (!tx_cur && !rx_cur)
+-				continue;
+-
+-			ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
+-
+-			spin_lock_bh(&vow->lock);
+-			vow->tx_airtime += tx_cur;
+-			spin_unlock_bh(&vow->lock);
+-		}
+-
+-		/* get signal strength of resp frames (CTS/BA/ACK) */
+-		addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
+-		val = mt76_rr(dev, addr);
+-
+-		rssi[0] = to_rssi(GENMASK(7, 0), val);
+-		rssi[1] = to_rssi(GENMASK(15, 8), val);
+-		rssi[2] = to_rssi(GENMASK(23, 16), val);
+-		rssi[3] = to_rssi(GENMASK(31, 14), val);
+-
+-		msta->ack_signal =
+-			mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
+-
+-		ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
+-	}
+-
+-	rcu_read_unlock();
+-}
+-
+ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+ 			      struct ieee80211_vif *vif, bool enable)
+ {
+@@ -1206,8 +1100,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 		}
+ 	}
+ 
+-	mt7996_mac_sta_poll(dev);
+-
+ 	if (wake)
+ 		mt76_set_tx_blocked(&dev->mt76, false);
+ 
+@@ -2369,31 +2261,42 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
+ 
+ void mt7996_mac_work(struct work_struct *work)
+ {
+-	struct mt7996_phy *phy;
+-	struct mt76_phy *mphy;
+-
+-	mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
+-					       mac_work.work);
+-	phy = mphy->priv;
++	struct mt76_phy *mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
++	                                                        mac_work.work);
++	struct mt7996_phy *phy = mphy->priv;
++	struct mt76_dev *mdev = mphy->dev;
+ 
+-	mutex_lock(&mphy->dev->mutex);
++	mutex_lock(&mdev->mutex);
+ 
+ 	mt76_update_survey(mphy);
+ 	if (++mphy->mac_work_count == 5) {
++		int i;
++
+ 		mphy->mac_work_count = 0;
+ 
+ 		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);
++		/* Update DEV-wise information only in
++		 * the MAC work of the first band running.
++		 */
++		for (i = MT_BAND0; i <= mphy->band_idx; ++i) {
++			if (i == mphy->band_idx) {
++				mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_RATE);
++				mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_AIRTIME);
++				mt7996_mcu_get_rssi(mdev);
++				if (mtk_wed_device_active(&mdev->mmio.wed)) {
++					mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_ADM_STAT);
++					mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_MSDU_COUNT);
++				}
++			} else if (mt7996_band_valid(phy->dev, i) &&
++			           test_bit(MT76_STATE_RUNNING, &mdev->phys[i]->state))
++				break;
+ 		}
+ 	}
+ 
+-	mutex_unlock(&mphy->dev->mutex);
++	mutex_unlock(&mdev->mutex);
+ 
+-	mt76_tx_status_check(mphy->dev, false);
++	mt76_tx_status_check(mdev, false);
+ 
+ 	ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
+ 				     MT7996_WATCHDOG_TIME);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 57af55ec..b849ebe1 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -560,7 +560,8 @@ 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, tx_packets, rx_packets;
++		struct ieee80211_sta *sta;
++		u32 tx_bytes, rx_bytes, tx_airtime, rx_airtime, tx_packets, rx_packets;
+ 
+ 		switch (le16_to_cpu(res->tag)) {
+ 		case UNI_ALL_STA_TXRX_RATE:
+@@ -581,7 +582,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 				break;
+ 
+ 			mphy = mt76_dev_phy(&dev->mt76, wcid->phy_idx);
+-			for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
++			for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; 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]);
+ 
+@@ -613,6 +614,24 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 			__mt7996_stat_to_netdev(mphy, wcid, 0, 0,
+ 						tx_packets, rx_packets);
+ 			break;
++		case UNI_ALL_STA_TXRX_AIRTIME:
++			wlan_idx = le16_to_cpu(res->airtime[i].wlan_idx);
++			wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
++			sta = wcid_to_sta(wcid);
++			if (!sta)
++				continue;
++
++			for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ++ac) {
++				u8 lmac_ac = mt76_connac_lmac_mapping(ac);
++				tx_airtime = le32_to_cpu(res->airtime[i].tx[lmac_ac]);
++				rx_airtime = le32_to_cpu(res->airtime[i].rx[lmac_ac]);
++
++				wcid->stats.tx_airtime += tx_airtime;
++				wcid->stats.rx_airtime += rx_airtime;
++				ieee80211_sta_register_airtime(sta, mt76_ac_to_tid(ac),
++				                               tx_airtime, rx_airtime);
++			}
++			break;
+ 		default:
+ 			break;
+ 		}
+@@ -2239,8 +2258,6 @@ mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
+ 	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;
+-	vow->tx_airtime = 0;
+-	spin_lock_init(&vow->lock);
+ 
+ 	ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
+ 	if (ret)
+@@ -4844,9 +4861,155 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
+ 				 sizeof(req), true);
+ }
+ 
+-int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
++int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
++	                        u16 sta_num, u16 *sta_list)
++{
++#define PER_STA_INFO_MAX_NUM	90
++	struct mt7996_mcu_per_sta_info_event *res;
++	struct mt76_wcid *wcid;
++	struct sk_buff *skb;
++	u16 wlan_idx;
++	int i, ret;
++	struct {
++		u8 __rsv1;
++		u8 unsolicit;
++		u8 __rsv2[2];
++
++		__le16 tag;
++		__le16 len;
++		__le16 sta_num;
++		u8 __rsv3[2];
++		__le16 sta_list[PER_STA_INFO_MAX_NUM];
++	} __packed req = {
++		.unsolicit = 0,
++		.tag = cpu_to_le16(tag),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.sta_num = cpu_to_le16(sta_num)
++	};
++
++	if (sta_num > PER_STA_INFO_MAX_NUM)
++		return -EINVAL;
++
++	for (i = 0; i < sta_num; ++i)
++		req.sta_list[i] = cpu_to_le16(sta_list[i]);
++
++	ret = mt76_mcu_send_and_get_msg(dev, MCU_WM_UNI_CMD(PER_STA_INFO),
++	                                &req, sizeof(req), true, &skb);
++	if (ret)
++		return ret;
++
++	res = (struct mt7996_mcu_per_sta_info_event *)skb->data;
++	if (le16_to_cpu(res->tag) != tag) {
++		ret = -EINVAL;
++		goto out;
++	}
++
++	rcu_read_lock();
++	switch (tag) {
++	case UNI_PER_STA_RSSI:
++		for (i = 0; i < sta_num; ++i) {
++			struct mt7996_sta *msta;
++			struct mt76_phy *phy;
++			s8 rssi[4];
++			u8 *rcpi;
++
++			wlan_idx = le16_to_cpu(res->rssi[i].wlan_idx);
++			wcid = rcu_dereference(dev->wcid[wlan_idx]);
++			if (wcid) {
++				rcpi = res->rssi[i].rcpi;
++				rssi[0] = to_rssi(MT_PRXV_RCPI0, rcpi[0]);
++				rssi[1] = to_rssi(MT_PRXV_RCPI0, rcpi[1]);
++				rssi[2] = to_rssi(MT_PRXV_RCPI0, rcpi[2]);
++				rssi[3] = to_rssi(MT_PRXV_RCPI0, rcpi[3]);
++
++				msta = container_of(wcid, struct mt7996_sta, wcid);
++				phy = msta->vif->phy->mt76;
++				msta->ack_signal = mt76_rx_signal(phy->antenna_mask, rssi);
++				ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
++			} else {
++				ret = -EINVAL;
++				dev_err(dev->dev, "Failed to update RSSI for "
++				                  "invalid WCID: %hu\n", wlan_idx);
++			}
++		}
++		break;
++	case UNI_PER_STA_TX_CNT:
++		for (i = 0; i < sta_num; ++i) {
++			wlan_idx = le16_to_cpu(res->tx_cnt[i].wlan_idx);
++			wcid = rcu_dereference(dev->wcid[wlan_idx]);
++			if (wcid) {
++				wcid->stats.tx_total_mpdu_cnt +=
++				            le32_to_cpu(res->tx_cnt[i].total);
++				wcid->stats.tx_failed_mpdu_cnt +=
++				            le32_to_cpu(res->tx_cnt[i].failed);
++			} else {
++				ret = -EINVAL;
++				dev_err(dev->dev, "Failed to update TX MPDU counts "
++				                  "for invalid WCID: %hu\n", wlan_idx);
++			}
++		}
++		break;
++	default:
++		ret = -EINVAL;
++		dev_err(dev->dev, "Unknown UNI_PER_STA_INFO_TAG: %d\n", tag);
++	}
++	rcu_read_unlock();
++out:
++	dev_kfree_skb(skb);
++	return ret;
++}
++
++int mt7996_mcu_get_rssi(struct mt76_dev *dev)
++{
++	u16 sta_list[PER_STA_INFO_MAX_NUM];
++	LIST_HEAD(sta_poll_list);
++	struct mt7996_sta *msta;
++	int i, ret;
++	bool empty = false;
++
++	spin_lock_bh(&dev->sta_poll_lock);
++	list_splice_init(&dev->sta_poll_list, &sta_poll_list);
++	spin_unlock_bh(&dev->sta_poll_lock);
++
++	while (!empty) {
++		for (i = 0; i < PER_STA_INFO_MAX_NUM; ++i) {
++			spin_lock_bh(&dev->sta_poll_lock);
++			if (list_empty(&sta_poll_list)) {
++				spin_unlock_bh(&dev->sta_poll_lock);
++
++				if (i == 0)
++					return 0;
++
++				empty = true;
++				break;
++			}
++			msta = list_first_entry(&sta_poll_list,
++			                        struct mt7996_sta,
++			                        wcid.poll_list);
++			list_del_init(&msta->wcid.poll_list);
++			spin_unlock_bh(&dev->sta_poll_lock);
++
++			sta_list[i] = msta->wcid.idx;
++		}
++
++		ret = mt7996_mcu_get_per_sta_info(dev, UNI_PER_STA_RSSI,
++		                                  i, sta_list);
++		if (ret) {
++			/* Add STAs, whose RSSI has not been updated,
++			 * back to polling list.
++			 */
++			spin_lock_bh(&dev->sta_poll_lock);
++			list_splice(&sta_poll_list, &dev->sta_poll_list);
++			spin_unlock_bh(&dev->sta_poll_lock);
++			break;
++		}
++	}
++
++	return ret;
++}
++
++int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag)
+ {
+-	struct mt7996_dev *dev = phy->dev;
+ 	struct {
+ 		u8 _rsv[4];
+ 
+@@ -4857,7 +5020,7 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+ 		.len = cpu_to_le16(sizeof(req) - 4),
+ 	};
+ 
+-	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
++	return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(ALL_STA_INFO),
+ 				 &req, sizeof(req), false);
+ }
+ 
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index a05dd6a5..cd327451 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -199,6 +199,31 @@ struct mt7996_mcu_mib {
+ 	__le64 data;
+ } __packed;
+ 
++struct per_sta_rssi {
++	__le16 wlan_idx;
++	u8 __rsv[2];
++	u8 rcpi[4];
++} __packed;
++
++struct per_sta_tx_cnt {
++	__le16 wlan_idx;
++	u8 __rsv[2];
++	__le32 total;
++	__le32 failed;
++} __packed;
++
++struct mt7996_mcu_per_sta_info_event {
++	u8 __rsv[4];
++
++	__le16 tag;
++	__le16 len;
++
++	union {
++		struct per_sta_rssi rssi[0];
++		struct per_sta_tx_cnt tx_cnt[0];
++	};
++} __packed;
++
+ struct all_sta_trx_rate {
+ 	__le16 wlan_idx;
+ 	u8 __rsv1[2];
+@@ -237,13 +262,18 @@ struct mt7996_mcu_all_sta_info_event {
+ 			__le32 tx_bytes[IEEE80211_NUM_ACS];
+ 			__le32 rx_bytes[IEEE80211_NUM_ACS];
+ 		} adm_stat[0] __packed;
+-
+ 		struct {
+ 			__le16 wlan_idx;
+ 			u8 rsv[2];
+ 			__le32 tx_msdu_cnt;
+ 			__le32 rx_msdu_cnt;
+ 		} msdu_cnt[0] __packed;
++		struct {
++			__le16 wlan_idx;
++			u8 __rsv[2];
++			__le32 tx[IEEE80211_NUM_ACS];
++			__le32 rx[IEEE80211_NUM_ACS];
++		} airtime[0] __packed;
+ 	} __packed;
+ } __packed;
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 677f00b0..c128fb8e 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -126,6 +126,8 @@
+ #define MT7996_RRO_MSDU_PG_CR_CNT 8
+ #define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
+ 
++#define to_rssi(field, rcpi)	((FIELD_GET(field, rcpi) - 220) / 2)
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -298,8 +300,6 @@ struct mt7996_vow_sta_ctrl {
+ 	bool paused;
+ 	u8 bss_grp_idx;
+ 	u8 drr_quantum[IEEE80211_NUM_ACS];
+-	u64 tx_airtime;
+-	spinlock_t lock;
+ };
+ 
+ struct mt7996_sta {
+@@ -308,7 +308,6 @@ struct mt7996_sta {
+ 	struct mt7996_vif *vif;
+ 
+ 	struct list_head rc_list;
+-	u32 airtime_ac[8];
+ 
+ 	int ack_signal;
+ 	struct ewma_avg_signal avg_ack_signal;
+@@ -404,6 +403,21 @@ struct mt7996_air_monitor_ctrl {
+ };
+ #endif
+ 
++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_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -592,6 +606,7 @@ struct mt7996_dev {
+ 		u32 fw_dbg_module;
+ 		u8 fw_dbg_lv;
+ 		u32 bcn_total_cnt[__MT_MAX_BAND];
++		u32 sid;
+ 	} dbg;
+ 	const struct mt7996_dbg_reg_desc *dbg_reg;
+ #endif
+@@ -797,7 +812,10 @@ 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);
++int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
++	                        u16 sta_num, u16 *sta_list);
++int mt7996_mcu_get_rssi(struct mt76_dev *dev);
++int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag);
+ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
+ 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);
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index c1764824..3b5ae7ac 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2951,6 +2951,69 @@ mt7996_vow_drr_dbg(void *data, u64 val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_vow_drr_dbg, NULL,
+ 			 mt7996_vow_drr_dbg, "%lld\n");
+ 
++static int
++mt7996_rro_session_read(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt7996_rro_ba_session *tbl;
++	u32 value[2];
++
++	mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC +
++		(dev->dbg.sid >> 1) + 0x200);
++
++	if (dev->dbg.sid & 0x1) {
++		value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
++		value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(3));
++	} else {
++		value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
++		value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
++	}
++
++	tbl = (struct mt7996_rro_ba_session *)&value[0];
++
++	seq_printf(s, " seid %d:\nba session table DW0:%08x DW2:%08x\n",
++		   dev->dbg.sid, value[0], value[1]);
++
++	seq_printf(s, "ack_sn = 0x%x, last_in_sn = 0x%x, sat/bn/bc/bd/cn = %d/%d/%d/%d/%d\n",
++		   tbl->ack_sn, tbl->last_in_sn, tbl->sat, tbl->bn, tbl->bc, tbl->bd, tbl->cn);
++
++	seq_printf(s, "within_cnt = %d, to_sel = %d, last_in_rxtime = %d\n",
++		   tbl->within_cnt, tbl->to_sel, tbl->last_in_rxtime);
++
++	return 0;
++}
++
++static int
++mt7996_show_rro_mib(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	u32 reg[12];
++
++	seq_printf(s, "RRO mib Info:\n");
++
++	reg[0] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(0));
++	reg[1] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(1));
++	reg[2] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(2));
++	reg[3] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(3));
++	reg[4] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(4));
++	reg[5] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(5));
++	reg[6] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(6));
++	reg[7] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(7));
++	reg[8] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(8));
++	reg[9] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(9));
++	reg[10] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(10));
++	reg[11] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(11));
++
++	seq_printf(s, "STEP_ONE/WITHIN/SURPASS = %x/%x/%x\n", reg[0], reg[3], reg[4]);
++	seq_printf(s, "REPEAT/OLDPKT/BAR = %x/%x/%x\n", reg[1], reg[2], reg[5]);
++	seq_printf(s, "SURPASS with big gap = %x\n", reg[6]);
++	seq_printf(s, "DISCONNECT/INVALID = %x/%x\n", reg[7], reg[8]);
++	seq_printf(s, "TO(Step one)/TO(flush all) = %x/%x\n", reg[9], reg[10]);
++	seq_printf(s, "buf ran out = %x\n", reg[11]);
++
++	return 0;
++}
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -3049,6 +3112,14 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 
+ 	debugfs_create_file("muru_prot_thr", 0200, dir, phy, &fops_muru_prot_thr);
+ 
++	if (dev->has_rro) {
++		debugfs_create_u32("rro_sid", 0600, dir, &dev->dbg.sid);
++		debugfs_create_devm_seqfile(dev->mt76.dev, "rro_sid_info", dir,
++					    mt7996_rro_session_read);
++		debugfs_create_devm_seqfile(dev->mt76.dev, "rro_mib", dir,
++					    mt7996_show_rro_mib);
++	}
++
+ 	return 0;
+ }
+ 
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index a3b62339..476b23c3 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -122,6 +122,8 @@ enum offs_rev {
+ #define MT_MCU_INT_EVENT_DMA_INIT		BIT(1)
+ #define MT_MCU_INT_EVENT_RESET_DONE		BIT(3)
+ 
++#define WF_RRO_TOP_STATISTIC(_n)		MT_RRO_TOP(0x180 + _n * 0x4)
++
+ /* PLE */
+ #define MT_PLE_BASE				0x820c0000
+ #define MT_PLE(ofs)				(MT_PLE_BASE + (ofs))
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch
deleted file mode 100644
index a6ffa60..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2999-wifi-mt76-mt7996-support-backaward-compatiable.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-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
-