[Refactor and sync kernel/wifi from Openwrt]

[Description]
Refactor and sync kernel/wifi from Openwrt

[Release-log]
N/A

diff --git a/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch b/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch
new file mode 100644
index 0000000..dc04e36
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch
@@ -0,0 +1,56 @@
+From 5b712b2ec82bb9e88346b379b5c6645b1fa7d7fe Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Wed, 6 Jul 2022 21:52:45 +0800
+Subject: [PATCH] mt76: testmode: use random payload for tx packets
+
+Compared to fixed payload packets, random payload packets have better
+measured EVM under the same txpower. Our tests show EVM becomes at least
+3 dB better in test cases with high rate and long tx length, which also
+aligns the testing result of proprietary driver.
+
+Suggested-by: Jm Chen <jm.chen@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/testmode.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/testmode.c b/testmode.c
+index 4a24f6c9..31439b39 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -1,5 +1,7 @@
+ // SPDX-License-Identifier: ISC
+ /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
++
++#include <linux/random.h>
+ #include "mt76.h"
+ 
+ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+@@ -124,12 +126,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+ 	if (!head)
+ 		return -ENOMEM;
+ 
+-	hdr = __skb_put_zero(head, head_len);
++	hdr = __skb_put_zero(head, sizeof(*hdr));
+ 	hdr->frame_control = cpu_to_le16(fc);
+ 	memcpy(hdr->addr1, td->addr[0], ETH_ALEN);
+ 	memcpy(hdr->addr2, td->addr[1], ETH_ALEN);
+ 	memcpy(hdr->addr3, td->addr[2], ETH_ALEN);
+ 	skb_set_queue_mapping(head, IEEE80211_AC_BE);
++	get_random_bytes(__skb_put(head, head_len - sizeof(*hdr)),
++			 head_len - sizeof(*hdr));
+ 
+ 	info = IEEE80211_SKB_CB(head);
+ 	info->flags = IEEE80211_TX_CTL_INJECTED |
+@@ -157,7 +161,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+ 			return -ENOMEM;
+ 		}
+ 
+-		__skb_put_zero(frag, frag_len);
++		get_random_bytes(__skb_put(frag, frag_len), frag_len);
+ 		head->len += frag->len;
+ 		head->data_len += frag->len;
+ 
+-- 
+2.25.1
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch b/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch
new file mode 100644
index 0000000..c25f9b2
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch
@@ -0,0 +1,245 @@
+From c1e72950b8f7df7c36c64e27613637f88e3c1ba3 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Fri, 24 Jun 2022 11:15:45 +0800
+Subject: [PATCH 1117/1117] mt76: mt7915: add vendor subcmd EDCCA ctrl
+
+Change-Id: I92dabf8be9c5a7ecec78f35325bc5645af8d15ab
+---
+ mt76_connac_mcu.h |  1 +
+ mt7915/main.c     |  3 +++
+ mt7915/mcu.c      | 38 ++++++++++++++++++++++++++++
+ mt7915/mcu.h      | 12 +++++++++
+ mt7915/mt7915.h   |  2 ++
+ mt7915/vendor.c   | 63 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7915/vendor.h   | 19 ++++++++++++++
+ 7 files changed, 138 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index a0e6fa6e..1747e06d 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1147,6 +1147,7 @@ enum {
+ 	MCU_EXT_CMD_SMESH_CTRL = 0xae,
+ 	MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
+ 	MCU_EXT_CMD_CERT_CFG = 0xb7,
++	MCU_EXT_CMD_EDCCA = 0xba,
+ 	MCU_EXT_CMD_CSI_CTRL = 0xc2,
+ };
+ 
+diff --git a/mt7915/main.c b/mt7915/main.c
+index 6c97ce78..1dc41ab6 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -456,6 +456,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
+ 			mutex_unlock(&dev->mt76.mutex);
+ 		}
+ #endif
++		ret = mt7915_mcu_set_edcca(phy, EDCCA_CTRL_SET_EN, NULL, 0);
++		if (ret)
++			return ret;
+ 		ieee80211_stop_queues(hw);
+ 		ret = mt7915_set_channel(phy);
+ 		if (ret)
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 46eef36a..205ecbab 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -4217,3 +4217,41 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
+ 
+ 	return 0;
+ }
++
++int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value,
++			 s8 compensation)
++{
++	static const u8 ch_band[] = {
++		[NL80211_BAND_2GHZ] = 0,
++		[NL80211_BAND_5GHZ] = 1,
++		[NL80211_BAND_6GHZ] = 2,
++	};
++	struct mt7915_dev *dev = phy->dev;
++	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
++	struct {
++		u8 band_idx;
++		u8 cmd_idx;
++		u8 setting[3];
++		bool record_in_fw;
++		u8 region;
++		s8 thres_compensation;
++	} __packed req = {
++		.band_idx = phy->band_idx,
++		.cmd_idx = mode,
++		.record_in_fw = false,
++		.region = dev->mt76.region,
++		.thres_compensation = compensation,
++	};
++
++	if (ch_band[chandef->chan->band] != 2)
++		return 0;
++
++	if (mode == EDCCA_CTRL_SET_EN) {
++		if (!value)
++			req.setting[0] = EDCCA_MODE_AUTO;
++		else
++			req.setting[0] = value[0];
++	}
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCCA), &req, sizeof(req), true);
++}
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index 873a8055..72c2cfc6 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -785,4 +785,16 @@ enum {
+ };
+ #endif
+ 
++enum {
++   EDCCA_CTRL_SET_EN = 0,
++   EDCCA_CTRL_SET_THERS,
++   EDCCA_CTRL_GET_EN,
++   EDCCA_CTRL_GET_THERS,
++   EDCCA_CTRL_NUM,
++};
++
++enum {
++   EDCCA_MODE_FORCE_DISABLE,
++   EDCCA_MODE_AUTO,
++};
+ #endif
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 0b7f73b3..5c58a29c 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -718,6 +718,8 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb);
+ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
+ 				  struct ieee80211_sta *sta);
+ #endif
++int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value,
++			 s8 compensation);
+ 
+ #ifdef MTK_DEBUG
+ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir);
+diff --git a/mt7915/vendor.c b/mt7915/vendor.c
+index 77d71e48..5a28a554 100644
+--- a/mt7915/vendor.c
++++ b/mt7915/vendor.c
+@@ -62,6 +62,17 @@ phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = {
+ 	[MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_STA] = { .type = NLA_U16 },
+ };
+ 
++static const struct nla_policy
++edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
++       [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_S8 },
++};
++
++
+ struct csi_null_tone {
+ 	u8 start;
+ 	u8 end;
+@@ -1015,6 +1026,47 @@ mt7915_vendor_phy_capa_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return len;
+ }
+ 
++static int mt7915_vendor_edcca_ctrl(struct wiphy *wiphy,
++				  struct wireless_dev *wdev,
++				  const void *data,
++				  int data_len)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct mt7915_phy *phy = mt7915_hw_phy(hw);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
++	int err;
++	u8 edcca_mode;
++	s8 edcca_compensation;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
++			edcca_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
++		return -EINVAL;
++
++	edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
++	if (edcca_mode == EDCCA_CTRL_SET_EN) {
++		u8 edcca_value[3] = {0};
++		if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] ||
++			!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE]) {
++			return -EINVAL;
++		}
++		edcca_value[0] =
++			nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
++		edcca_compensation =
++			nla_get_s8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE]);
++
++		err = mt7915_mcu_set_edcca(phy, edcca_mode, edcca_value,
++					 edcca_compensation);
++		if (err)
++			return err;
++	}
++	return 0;
++}
++
++
+ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -1083,6 +1135,17 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ 		.dumpit = mt7915_vendor_phy_capa_ctrl_dump,
+ 		.policy = phy_capa_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_PHY_CAPA_CTRL_MAX,
++	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7915_vendor_edcca_ctrl,
++		.policy = edcca_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
+ 	}
+ };
+ 
+diff --git a/mt7915/vendor.h b/mt7915/vendor.h
+index 719b851f..83c41bc1 100644
+--- a/mt7915/vendor.h
++++ b/mt7915/vendor.h
+@@ -10,8 +10,27 @@ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
+ 	MTK_NL80211_VENDOR_SUBCMD_HEMU_CTRL = 0xc5,
+ 	MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL = 0xc6,
++	MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ };
+ 
++
++enum mtk_vendor_attr_edcca_ctrl {
++        MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
++
++        MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
++
++        /* keep last */
++        NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
++        MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
++                NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
++};
++
++
+ enum mtk_capi_control_changed {
+ 	CAPI_RFEATURE_CHANGED		= BIT(16),
+ 	CAPI_WIRELESS_CHANGED		= BIT(17),
+-- 
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
index 5c5a05d..7040ca6 100755
--- a/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
+++ b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
@@ -5,10 +5,10 @@
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
- dma.c             | 219 +++++++++++++++++++++++++++++++++--------
+ dma.c             | 248 +++++++++++++++++++++++++++++++++--------
  dma.h             |  10 ++
  mac80211.c        |   8 +-
- mt76.h            |  24 ++++-
+ mt76.h            |  24 +++-
  mt7603/dma.c      |   2 +-
  mt7603/mt7603.h   |   2 +-
  mt7615/mac.c      |   2 +-
@@ -17,7 +17,7 @@
  mt76x02.h         |   2 +-
  mt76x02_txrx.c    |   2 +-
  mt7915/dma.c      |  10 ++
- mt7915/mac.c      |  89 ++++++++++++++++-
+ mt7915/mac.c      | 101 ++++++++++++++++-
  mt7915/mcu.c      |   3 +
  mt7915/mmio.c     |  26 ++++-
  mt7915/mt7915.h   |   7 +-
@@ -25,13 +25,11 @@
  mt7921/mac.c      |   2 +-
  mt7921/mt7921.h   |   4 +-
  mt7921/pci_mac.c  |   4 +-
- tx.c              |  34 +++++++
- 21 files changed, 410 insertions(+), 65 deletions(-)
- mode change 100755 => 100644 mt7915/mac.c
- mode change 100755 => 100644 mt7915/mmio.c
+ tx.c              |  34 ++++++
+ 21 files changed, 448 insertions(+), 68 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 03ee910..094aede 100644
+index 03ee910..e46dbed 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -98,6 +98,63 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
@@ -98,7 +96,29 @@
  static void
  mt76_free_pending_txwi(struct mt76_dev *dev)
  {
-@@ -141,12 +198,15 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -112,6 +169,21 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+ 	local_bh_enable();
+ }
+ 
++static void
++mt76_free_pending_rxwi(struct mt76_dev *dev)
++{
++	struct mt76_txwi_cache *r;
++
++	local_bh_disable();
++	while ((r = __mt76_get_rxwi(dev)) != NULL) {
++		if (r->buf)
++			skb_free_frag(r->buf);
++
++		kfree(r);
++	}
++	local_bh_enable();
++}
++
+ static void
+ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+@@ -141,12 +213,15 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
  static int
  mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
  		 struct mt76_queue_buf *buf, int nbufs, u32 info,
@@ -115,7 +135,7 @@
  
  	if (txwi) {
  		q->entry[q->head].txwi = DMA_DUMMY_DATA;
-@@ -162,28 +222,42 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -162,28 +237,42 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
  		desc = &q->desc[idx];
  		entry = &q->entry[idx];
  
@@ -178,7 +198,7 @@
  		WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
  		WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
  		WRITE_ONCE(desc->info, cpu_to_le32(info));
-@@ -272,33 +346,63 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+@@ -272,33 +361,63 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
  
  static void *
  mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
@@ -248,7 +268,7 @@
  {
  	int idx = q->tail;
  
-@@ -314,7 +418,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+@@ -314,7 +433,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
  	q->tail = (q->tail + 1) % q->ndesc;
  	q->queued--;
  
@@ -257,7 +277,7 @@
  }
  
  static int
-@@ -336,7 +440,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -336,7 +455,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
  	buf.len = skb->len;
  
  	spin_lock_bh(&q->lock);
@@ -266,7 +286,7 @@
  	mt76_dma_kick_queue(dev, q);
  	spin_unlock_bh(&q->lock);
  
-@@ -413,7 +517,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -413,7 +532,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
  		goto unmap;
  
  	return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
@@ -275,15 +295,16 @@
  
  unmap:
  	for (n--; n > 0; n--)
-@@ -448,6 +552,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -448,6 +567,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
  	int frames = 0;
  	int len = SKB_WITH_OVERHEAD(q->buf_size);
  	int offset = q->buf_offset;
 +	struct mtk_wed_device *wed = &dev->mmio.wed;
++	struct page_frag_cache *rx_page;
  
  	if (!q->ndesc)
  		return 0;
-@@ -456,10 +561,27 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -456,10 +577,29 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
  
  	while (q->queued < q->ndesc - 1) {
  		struct mt76_queue_buf qbuf;
@@ -291,7 +312,9 @@
 +		bool skip_alloc = false;
 +		struct mt76_txwi_cache *r = NULL;
 +
++		rx_page = &q->rx_page;
 +		if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) {
++			rx_page = &wed->rx_page;
 +			r = mt76_get_rxwi(dev);
 +			if (!r)
 +				return -ENOMEM;
@@ -307,14 +330,14 @@
 -		if (!buf)
 -			break;
 +		if (!skip_alloc) {
-+			buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++			buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC);
 +			if (!buf)
 +				break;
 +		}
  
  		addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
  		if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
-@@ -470,7 +592,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -470,7 +610,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
  		qbuf.addr = addr + offset;
  		qbuf.len = len - offset;
  		qbuf.skip_unmap = false;
@@ -323,7 +346,7 @@
  		frames++;
  	}
  
-@@ -516,6 +638,11 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -516,6 +656,11 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
  		if (!ret)
  			q->wed_regs = wed->txfree_ring.reg_base;
  		break;
@@ -335,7 +358,7 @@
  	default:
  		ret = -EINVAL;
  	}
-@@ -531,7 +658,8 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -531,7 +676,8 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  		     int idx, int n_desc, int bufsize,
  		     u32 ring_base)
  {
@@ -345,7 +368,7 @@
  
  	spin_lock_init(&q->lock);
  	spin_lock_init(&q->cleanup_lock);
-@@ -541,6 +669,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -541,6 +687,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  	q->buf_size = bufsize;
  	q->hw_idx = idx;
  
@@ -357,7 +380,7 @@
  	size = q->ndesc * sizeof(struct mt76_desc);
  	q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
  	if (!q->desc)
-@@ -573,7 +706,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -573,7 +724,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  
  	spin_lock_bh(&q->lock);
  	do {
@@ -366,7 +389,7 @@
  		if (!buf)
  			break;
  
-@@ -614,7 +747,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -614,7 +765,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
  
  static void
  mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
@@ -375,7 +398,7 @@
  {
  	struct sk_buff *skb = q->rx_head;
  	struct skb_shared_info *shinfo = skb_shinfo(skb);
-@@ -634,7 +767,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -634,7 +785,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
  
  	q->rx_head = NULL;
  	if (nr_frags < ARRAY_SIZE(shinfo->frags))
@@ -384,7 +407,7 @@
  	else
  		dev_kfree_skb(skb);
  }
-@@ -655,6 +788,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -655,6 +806,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  	}
  
  	while (done < budget) {
@@ -392,7 +415,7 @@
  		u32 info;
  
  		if (check_ddone) {
-@@ -665,10 +799,13 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -665,10 +817,13 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  				break;
  		}
  
@@ -407,7 +430,7 @@
  		if (q->rx_head)
  			data_len = q->buf_size;
  		else
-@@ -681,7 +818,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -681,7 +836,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		}
  
  		if (q->rx_head) {
@@ -416,7 +439,7 @@
  			continue;
  		}
  
-@@ -708,7 +845,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -708,7 +863,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  			continue;
  		}
  
@@ -425,6 +448,36 @@
  		continue;
  
  free_frag:
+@@ -785,8 +940,8 @@ EXPORT_SYMBOL_GPL(mt76_dma_attach);
+ 
+ void mt76_dma_cleanup(struct mt76_dev *dev)
+ {
+-	int i;
+-
++	int i, type;
++
+ 	mt76_worker_disable(&dev->tx_worker);
+ 	netif_napi_del(&dev->tx_napi);
+ 
+@@ -801,12 +956,17 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ 
+ 	mt76_for_each_q_rx(dev, i) {
+ 		netif_napi_del(&dev->napi[i]);
+-		mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
++		type = FIELD_GET(MT_QFLAG_WED_TYPE, dev->q_rx[i].flags);
++		if (type != MT76_WED_Q_RX)
++			mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
+ 	}
+ 
+ 	mt76_free_pending_txwi(dev);
++	mt76_free_pending_rxwi(dev);
+ 
+ 	if (mtk_wed_device_active(&dev->mmio.wed))
+ 		mtk_wed_device_detach(&dev->mmio.wed);
++
++	mt76_free_pending_rxwi(dev);
+ }
+ EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
 diff --git a/dma.h b/dma.h
 index fdf786f..90370d1 100644
 --- a/dma.h
@@ -628,7 +681,7 @@
  int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
  		       struct ieee80211_sta *sta);
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index cd35068..f90a08f 100644
+index cd35068..2454846 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -1190,6 +1190,7 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
@@ -737,9 +790,7 @@
  				       MT_RXQ_ID(MT_RXQ_EXT),
  				       MT7915_RX_RING_SIZE,
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-old mode 100755
-new mode 100644
-index bc8da4d..79b7d01
+index bc8da4d..dd87a40 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -217,7 +217,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
@@ -751,23 +802,32 @@
  {
  	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
  	struct mt76_phy *mphy = &dev->mt76.phy;
+@@ -234,7 +234,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
+ 	bool unicast, insert_ccmp_hdr = false;
+ 	u8 remove_pad, amsdu_info;
+ 	u8 mode = 0, qos_ctl = 0;
+-	struct mt7915_sta *msta;
++	struct mt7915_sta *msta = NULL;
+ 	bool hdr_trans;
+ 	u16 hdr_gap;
+ 	u16 seq_ctrl = 0;
 @@ -494,6 +494,27 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
  #endif
  	} else {
  		status->flag |= RX_FLAG_8023;
-+		if (msta || msta->vif) {
++		if (msta && msta->vif) {
 +			struct mtk_wed_device *wed;
 +			int type;
 +
 +			wed = &dev->mt76.mmio.wed;
 +			type = FIELD_GET(MT_QFLAG_WED_TYPE, dev->mt76.q_rx[q].flags);
 +			if ((mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) &&
-+			    (info & MT_DMA_INFO_PPE_VLD)){
++			    (info & MT_DMA_INFO_PPE_VLD)) {
 +				struct ieee80211_vif *vif;
 +				u32 hash, reason;
 +
 +				vif = container_of((void *)msta->vif, struct ieee80211_vif,
-+					   drv_priv);
++						   drv_priv);
 +
 +				skb->dev = ieee80211_vif_to_netdev(vif);
 +				reason = FIELD_GET(MT_DMA_PPE_CPU_REASON, info);
@@ -779,7 +839,7 @@
  	}
  
  	if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
-@@ -840,6 +861,68 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+@@ -840,6 +861,80 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
  	return MT_TXD_TXP_BUF_SIZE;
  }
  
@@ -826,6 +886,7 @@
 +{
 +	struct mt76_txwi_cache *rxwi;
 +	struct mt7915_dev *dev;
++	struct page *page;
 +	int token;
 +
 +	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
@@ -835,6 +896,9 @@
 +		if(!rxwi)
 +			continue;
 +
++		if(!rxwi->buf)
++			continue;
++
 +		dma_unmap_single(dev->mt76.dma_dev, rxwi->dma_addr,
 +			 wed->wlan.rx_pkt_size, DMA_FROM_DEVICE);
 +		skb_free_frag(rxwi->buf);
@@ -842,13 +906,21 @@
 +
 +		mt76_put_rxwi(&dev->mt76, rxwi);
 +	}
++
++	if (wed->rx_page.va)
++		return;
++
++	page = virt_to_page(wed->rx_page.va);
++	__page_frag_cache_drain(page, wed->rx_page.pagecnt_bias);
++	memset(&wed->rx_page, 0, sizeof(wed->rx_page));
++
 +	return;
 +}
 +
  static void
  mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
  {
-@@ -1120,7 +1203,7 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
+@@ -1120,7 +1215,7 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
  }
  
  void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
@@ -857,7 +929,7 @@
  {
  	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
  	__le32 *rxd = (__le32 *)skb->data;
-@@ -1154,7 +1237,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+@@ -1154,7 +1249,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
  		dev_kfree_skb(skb);
  		break;
  	case PKT_TYPE_NORMAL:
@@ -867,7 +939,7 @@
  			return;
  		}
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 1468c3c..4f64df4 100644
+index 1468c3c..5eace9e 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -1704,6 +1704,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
@@ -888,9 +960,7 @@
  				     MCU_EXT_CMD(STA_REC_UPDATE), true);
  }
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-old mode 100755
-new mode 100644
-index b4a3120..08ff556
+index b4a3120..08ff556 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -28,6 +28,9 @@ static const u32 mt7915_reg[] = {
diff --git a/recipes-kernel/linux-mt76/files/patches/patches.inc b/recipes-kernel/linux-mt76/files/patches/patches.inc
index da26649..5297bc1 100644
--- a/recipes-kernel/linux-mt76/files/patches/patches.inc
+++ b/recipes-kernel/linux-mt76/files/patches/patches.inc
@@ -7,6 +7,7 @@
     file://0005-mt76-mt7915-drop-undefined-action-frame.patch \
     file://0008-mt76-common-RF-CR-idx-require-8-bits.patch \
     file://0010-mt76-mt7915-4addr-null-frame-using-fixed-rate-to-suc.patch \
+    file://0011-mt76-testmode-use-random-payload-for-tx-packets.patch \
     file://100-Revert-of-net-pass-the-dst-buffer-to-of_get_mac_addr.patch \
     file://1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch \
     file://1002-mt76-mt7915-csi-implement-csi-support.patch \
@@ -22,6 +23,7 @@
     file://1114-mt76-airtime-fairness-feature-off-in-mac80211.patch \
     file://1115-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch \
     file://1116-mt76-mt7915-add-vendor-dump-phy-capa.patch \
+    file://1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch \
     file://3001-mt76-add-wed-tx-support.patch \
     file://3002-mt76-add-wed-rx-support.patch \
     file://3003-mt76-add-fill-receive-path-to-report-wed-idx.patch \