[][MAC80211][WED][Refactor and sync wed patches from upstream]

[Description]
Refactor and sync wed patches from upstream

[Release-log]

Change-Id: I4e3dc38a67c3ec099ba59257442900ba92cc4198
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8706171
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch
deleted file mode 100644
index b90693d..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch
+++ /dev/null
@@ -1,3755 +0,0 @@
-From 542064ad977706558be071e0f7d706f5aa37f390 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Mon, 18 Sep 2023 13:21:15 +0800
-Subject: [PATCH 1/5] mtk:wed:add wed3 support
-
----
- arch/arm64/boot/dts/mediatek/mt7988.dtsi      |  152 ++-
- .../dts/mediatek/mt7988a-dsa-10g-spim-nor.dts |   16 +-
- .../dts/mediatek/mt7988d-dsa-10g-spim-nor.dts |   16 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.c   |    3 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |    5 +-
- drivers/net/ethernet/mediatek/mtk_ppe.c       |   17 +-
- drivers/net/ethernet/mediatek/mtk_ppe.h       |    2 +-
- .../net/ethernet/mediatek/mtk_ppe_offload.c   |   16 +-
- drivers/net/ethernet/mediatek/mtk_wed.c       | 1178 +++++++++++++----
- drivers/net/ethernet/mediatek/mtk_wed.h       |   25 +-
- .../net/ethernet/mediatek/mtk_wed_debugfs.c   |  584 +++++++-
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c   |   14 +-
- drivers/net/ethernet/mediatek/mtk_wed_mcu.h   |    5 +-
- drivers/net/ethernet/mediatek/mtk_wed_regs.h  |  338 ++++-
- include/linux/netdevice.h                     |    7 +
- include/linux/soc/mediatek/mtk_wed.h          |   83 +-
- 16 files changed, 2070 insertions(+), 391 deletions(-)
- mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
-
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-index 7e96640..3368240 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-@@ -193,44 +193,49 @@
- 		status = "disabled";
- 	};
- 
--	wed: wed@15010000 {
--		compatible = "mediatek,wed";
--		wed_num = <3>;
--		/* add this property for wed get the pci slot number. */
--		pci_slot_map = <0>, <1>, <2>;
--		reg = <0 0x15010000 0 0x2000>,
--		      <0 0x15012000 0 0x2000>,
--		      <0 0x15014000 0 0x2000>;
-+	wed0: wed@15010000 {
-+		compatible = "mediatek,mt7988-wed",
-+			     "syscon";
-+		reg = <0 0x15010000 0 0x2000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
--	};
--
--	wed2: wed2@15012000 {
--		compatible = "mediatek,wed2";
--		wed_num = <3>;
--		/* add this property for wed get the pci slot number. */
--		reg = <0 0x15010000 0 0x2000>,
--		      <0 0x15012000 0 0x2000>,
--		      <0 0x15014000 0 0x2000>;
-+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
-+		mediatek,wed_pcie = <&wed_pcie>;
-+		mediatek,ap2woccif = <&ap2woccif0>;
-+		mediatek,wocpu_ilm = <&wocpu0_ilm>;
-+		mediatek,wocpu_dlm = <&wocpu0_dlm>;
-+		mediatek,wocpu_boot = <&cpu0_boot>;
-+		mediatek,wocpu_emi = <&wocpu0_emi>;
-+		mediatek,wocpu_data = <&wocpu_data>;
-+	};
-+
-+	wed1: wed@15012000 {
-+		compatible = "mediatek,mt7988-wed",
-+                             "syscon";
-+		reg = <0 0x15012000 0 0x2000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
--	};
--
--	wed3: wed3@15014000 {
--		compatible = "mediatek,wed3";
--		wed_num = <3>;
--		/* add this property for wed get the pci slot number. */
--		reg = <0 0x15010000 0 0x2000>,
--		      <0 0x15012000 0 0x2000>,
--		      <0 0x15014000 0 0x2000>;
-+		interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-+		mediatek,wed_pcie = <&wed_pcie>;
-+		mediatek,ap2woccif = <&ap2woccif1>;
-+		mediatek,wocpu_ilm = <&wocpu1_ilm>;
-+		mediatek,wocpu_dlm = <&wocpu1_dlm>;
-+		mediatek,wocpu_boot = <&cpu1_boot>;
-+		mediatek,wocpu_emi = <&wocpu1_emi>;
-+		mediatek,wocpu_data = <&wocpu_data>;
-+	};
-+
-+	wed2: wed@15014000 {
-+		compatible = "mediatek,mt7988-wed",
-+                             "syscon";
-+		reg = <0 0x15014000 0 0x2000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
-+		interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
-+		mediatek,wed_pcie = <&wed_pcie>;
-+		mediatek,ap2woccif = <&ap2woccif2>;
-+		mediatek,wocpu_ilm = <&wocpu2_ilm>;
-+		mediatek,wocpu_dlm = <&wocpu2_dlm>;
-+		mediatek,wocpu_boot = <&cpu2_boot>;
-+		mediatek,wocpu_emi = <&wocpu2_emi>;
-+		mediatek,wocpu_data = <&wocpu_data>;
- 	};
- 
- 	wdma: wdma@15104800 {
-@@ -240,15 +245,25 @@
- 		      <0 0x15105000 0 0x400>;
- 	};
- 
--	ap2woccif: ap2woccif@151A5000 {
--		compatible = "mediatek,ap2woccif";
--		reg = <0 0x151A5000 0 0x1000>,
--		      <0 0x152A5000 0 0x1000>,
--		      <0 0x153A5000 0 0x1000>;
-+	ap2woccif0: ap2woccif@151A5000 {
-+		compatible = "mediatek,ap2woccif", "syscon";
-+		reg = <0 0x151A5000 0 0x1000>;
-+		interrupt-parent = <&gic>;
-+		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
-+	};
-+
-+	ap2woccif1: ap2woccif@152A5000 {
-+		compatible = "mediatek,ap2woccif", "syscon";
-+		reg = <0 0x152A5000 0 0x1000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
-+		interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
-+	};
-+
-+	ap2woccif2: ap2woccif@153A5000 {
-+		compatible = "mediatek,ap2woccif", "syscon";
-+		reg = <0 0x153A5000 0 0x1000>;
-+		interrupt-parent = <&gic>;
-+		interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
- 	};
- 
- 	wocpu0_ilm: wocpu0_ilm@151E0000 {
-@@ -256,31 +271,53 @@
- 		reg = <0 0x151E0000 0 0x8000>;
- 	};
- 
--	wocpu1_ilm: wocpu1_ilm@152E0000 {
--		compatible = "mediatek,wocpu1_ilm";
-+	wocpu1_ilm: wocpu_ilm@152E0000 {
-+		compatible = "mediatek,wocpu_ilm";
- 		reg = <0 0x152E0000 0 0x8000>;
- 	};
- 
--	wocpu2_ilm: wocpu2_ilm@153E0000 {
--		compatible = "mediatek,wocpu2_ilm";
--		reg = <0 0x153E0000 0 0x8000>;
-+	wocpu2_ilm: wocpu_ilm@153E0000 {
-+                compatible = "mediatek,wocpu_ilm";
-+                reg = <0 0x153E0000 0 0x8000>;
-+    };
-+
-+	wocpu0_dlm: wocpu_dlm@151E8000 {
-+		compatible = "mediatek,wocpu_dlm";
-+		reg = <0 0x151E8000 0 0x2000>;
-+
-+		resets = <&ethsysrst 0>;
-+		reset-names = "wocpu_rst";
-+	};
-+
-+	wocpu1_dlm: wocpu_dlm@0x152E8000 {
-+		compatible = "mediatek,wocpu_dlm";
-+		reg = <0 0x152E8000 0 0x2000>;
-+
-+		resets = <&ethsysrst 0>;
-+		reset-names = "wocpu_rst";
- 	};
- 
--	wocpu_dlm: wocpu_dlm@151E8000 {
-+	wocpu2_dlm: wocpu_dlm@0x153E8000 {
- 		compatible = "mediatek,wocpu_dlm";
--		reg = <0 0x151E8000 0 0x2000>,
--		      <0 0x152E8000 0 0x2000>,
--		      <0 0x153E8000 0 0x2000>;
-+		reg = <0 0x153E8000 0 0x2000>;
- 
- 		resets = <&ethsysrst 0>;
- 		reset-names = "wocpu_rst";
- 	};
- 
--	cpu_boot: wocpu_boot@15194000 {
--		compatible = "mediatek,wocpu_boot";
--		reg = <0 0x15194000 0 0x1000>,
--		      <0 0x15294000 0 0x1000>,
--		      <0 0x15394000 0 0x1000>;
-+	cpu0_boot: wocpu_boot@15194000 {
-+		compatible = "mediatek,wocpu0_boot";
-+		reg = <0 0x15194000 0 0x1000>;
-+	};
-+
-+	cpu1_boot: wocpu_boot@15294000 {
-+		compatible = "mediatek,wocpu1_boot";
-+		reg = <0 0x15294000 0 0x1000>;
-+	};
-+
-+	cpu2_boot: wocpu_boot@15394000 {
-+		compatible = "mediatek,wocpu2_boot";
-+		reg = <0 0x15394000 0 0x1000>;
- 	};
- 
- 	reserved-memory {
-@@ -901,6 +938,7 @@
- 					 <&topckgen CK_TOP_CB_NET2_D2>;
- 		mediatek,ethsys = <&ethsys>;
- 		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
-+		mediatek,wed = <&wed0>, <&wed1>, <&wed2>;
- 		mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
- 		mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
- 		mediatek,xfi_pll = <&xfi_pll>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-index 578a489..596f0ca 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-@@ -369,9 +369,23 @@
- 	status = "okay";
- };
- 
--&wed {
-+&wed0 {
- 	dy_txbm_enable = "true";
- 	dy_txbm_budge = <8>;
- 	txbm_init_sz = <10>;
- 	status = "okay";
- };
-+
-+&wed1 {
-+	dy_txbm_enable = "true";
-+	dy_txbm_budge = <8>;
-+	txbm_init_sz = <10>;
-+	status = "okay";
-+};
-+
-+&wed2 {
-+	dy_txbm_enable = "true";
-+	dy_txbm_budge = <8>;
-+	txbm_init_sz = <10>;
-+	status = "okay";
-+};
-\ No newline at end of file
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-index e743718..f430118 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-@@ -381,9 +381,23 @@
- 	status = "okay";
- };
- 
--&wed {
-+&wed0 {
- 	dy_txbm_enable = "true";
- 	dy_txbm_budge = <8>;
- 	txbm_init_sz = <10>;
- 	status = "okay";
- };
-+
-+&wed1 {
-+	dy_txbm_enable = "true";
-+	dy_txbm_budge = <8>;
-+	txbm_init_sz = <10>;
-+	status = "okay";
-+};
-+
-+&wed2 {
-+	dy_txbm_enable = "true";
-+	dy_txbm_budge = <8>;
-+	txbm_init_sz = <10>;
-+	status = "okay";
-+};
-\ No newline at end of file
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index c75ce25..ec78adf 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5216,7 +5216,8 @@ static int mtk_probe(struct platform_device *pdev)
- 							  "mediatek,wed", i);
- 		static const u32 wdma_regs[] = {
- 			MTK_WDMA0_BASE,
--			MTK_WDMA1_BASE
-+			MTK_WDMA1_BASE,
-+			MTK_WDMA2_BASE
- 		};
- 		void __iomem *wdma;
- 		u32 wdma_phy;
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 1074f46..a788d43 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -623,9 +623,12 @@
- #define RX_DMA_SPORT_MASK       0x7
- #define RX_DMA_SPORT_MASK_V2    0xf
- 
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
- #define MTK_WDMA0_BASE		0x4800
- #define MTK_WDMA1_BASE		0x4c00
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WDMA2_BASE		0x5000
-+#endif
- #else
- #define MTK_WDMA0_BASE		0x2800
- #define MTK_WDMA1_BASE		0x2c00
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-old mode 100755
-new mode 100644
-index 0e9c0bd..ae0acd5
---- a/drivers/net/ethernet/mediatek/mtk_ppe.c
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -9,6 +9,7 @@
- #include <linux/if_ether.h>
- #include <linux/if_vlan.h>
- #include <net/dsa.h>
-+#include <net/route.h>
- #include "mtk_eth_soc.h"
- #include "mtk_ppe.h"
- #include "mtk_ppe_regs.h"
-@@ -407,7 +408,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
- }
- 
- int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
--			   int bss, int wcid)
-+			   int bss, int wcid, bool amsdu_en)
- {
- 	struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
- 	u32 *ib2 = mtk_foe_entry_ib2(entry);
-@@ -419,6 +420,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
- 
- 	l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
- 		    FIELD_PREP(MTK_FOE_WINFO_BSS, bss);
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+	l2->winfo_pao = FIELD_PREP(MTK_FOE_WINFO_PAO_AMSDU_EN, amsdu_en);
-+#endif
- #else
- 	if (wdma_idx)
- 		*ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
-@@ -454,6 +458,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
- 	*ib2 &= ~MTK_FOE_IB2_DSCP;
- 	*ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
- 
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+	struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
-+
-+	if (*ib2 & MTK_FOE_IB2_WDMA_WINFO &&
-+	    l2->winfo_pao & MTK_FOE_WINFO_PAO_AMSDU_EN) {
-+		u8 tid = (dscp >> 5) & 0xf;
-+
-+		l2->winfo_pao |= FIELD_PREP(MTK_FOE_WINFO_PAO_TID, tid);
-+	}
-+#endif
-+
- 	return 0;
- }
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
-index 2a8b6ef..66c7f10 100644
---- a/drivers/net/ethernet/mediatek/mtk_ppe.h
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
-@@ -428,7 +428,7 @@ int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
- int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
- int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
- int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
--			   int bss, int wcid);
-+			   int bss, int wcid, bool amsdu_en);
- int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
- int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
- bool mtk_foe_entry_match(struct mtk_foe_entry *entry, struct mtk_foe_entry *data);
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-index 95174b7..339359e 100644
---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -112,6 +112,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
- 	info->queue = path.mtk_wdma.queue;
- 	info->bss = path.mtk_wdma.bss;
- 	info->wcid = path.mtk_wdma.wcid;
-+	info->amsdu_en = path.mtk_wdma.amsdu_en;
- 
- 	return 0;
- }
-@@ -193,13 +194,15 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
- 
- 	if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
- 		mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
--				       info.wcid);
-+				       info.wcid, info.amsdu_en);
- 		pse_port = PSE_PPE0_PORT;
- #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
- 		if (info.wdma_idx == 0)
- 			pse_port = PSE_WDMA0_PORT;
- 		else if (info.wdma_idx == 1)
- 			pse_port = PSE_WDMA1_PORT;
-+		else if (info.wdma_idx == 2)
-+			pse_port = PSE_WDMA2_PORT;
- 		else
- 			return -EOPNOTSUPP;
- #endif
-@@ -481,8 +484,6 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- 	if (data.pppoe.num == 1)
- 		mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
- 
--	mtk_foe_entry_set_dscp(&foe, dscp);
--
- 	mtk_foe_entry_set_sp(eth->ppe[ppe_index], &foe);
- 
- 	err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
-@@ -490,8 +491,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- 	if (err)
- 		return err;
- 
--	if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
--		return err;
-+	mtk_foe_entry_set_dscp(&foe, dscp);
-+	/*if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
-+		return err;*/
- 
- 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- 	if (!entry)
-@@ -516,8 +518,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- 	mtk_foe_entry_clear(eth->ppe[ppe_index], entry);
- free:
- 	kfree(entry);
--	if (wed_index >= 0)
--	    mtk_wed_flow_remove(wed_index);
-+	/*if (wed_index >= 0)
-+	    mtk_wed_flow_remove(wed_index);*/
- 	return err;
- }
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 48c35ae..561fc6c 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -28,7 +28,7 @@ struct wo_cmd_ring {
- 	u32 cnt;
- 	u32 unit;
- };
--static struct mtk_wed_hw *hw_list[2];
-+static struct mtk_wed_hw *hw_list[3];
- static DEFINE_MUTEX(hw_lock);
- 
- static void
-@@ -73,6 +73,26 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
- 	return wdma_r32(dev, MTK_WDMA_GLO_CFG);
- }
- 
-+static u32
-+mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
-+{
-+	if (wed_r32(dev, reg) & mask)
-+		return true;
-+
-+	return false;
-+}
-+
-+static int
-+mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
-+{
-+	int sleep = 1000;
-+	int timeout = 100 * sleep;
-+	u32 val;
-+
-+	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
-+				 timeout, false, dev, reg, mask);
-+}
-+
- static int
- mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- {
-@@ -235,6 +255,8 @@ mtk_wed_assign(struct mtk_wed_device *dev)
- 			continue;
- 
- 		hw->wed_dev = dev;
-+		hw->pci_base = MTK_WED_PCIE_BASE;
-+
- 		return hw;
- 	}
- 
-@@ -242,23 +264,84 @@ mtk_wed_assign(struct mtk_wed_device *dev)
- }
- 
- static int
--mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
-+mtk_wed_pao_buffer_alloc(struct mtk_wed_device *dev)
-+{
-+	struct mtk_wed_pao *pao;
-+	int i, j;
-+
-+	pao = kzalloc(sizeof(struct mtk_wed_pao), GFP_KERNEL);
-+	if (!pao)
-+		return -ENOMEM;
-+
-+	dev->hw->wed_pao = pao;
-+
-+	for (i = 0; i < 32; i++) {
-+		/* each segment is 64K*/
-+		pao->hif_txd[i] = (char *)__get_free_pages(GFP_ATOMIC |
-+							   GFP_DMA32 |
-+							   __GFP_ZERO, 4);
-+		if (!pao->hif_txd[i])
-+			goto err;
-+
-+		pao->hif_txd_phys[i] = dma_map_single(dev->hw->dev,
-+						      pao->hif_txd[i],
-+						      16 * PAGE_SIZE,
-+						      DMA_TO_DEVICE);
-+		if (unlikely(dma_mapping_error(dev->hw->dev,
-+					       pao->hif_txd_phys[i])))
-+			goto err;
-+	}
-+
-+	return 0;
-+
-+err:
-+	for (j = 0; j < i; j++)
-+		dma_unmap_single(dev->hw->dev, pao->hif_txd_phys[j],
-+			     16 * PAGE_SIZE, DMA_TO_DEVICE);
-+
-+	return -ENOMEM;
-+}
-+
-+static int
-+mtk_wed_pao_free_buffer(struct mtk_wed_device *dev)
-+{
-+	struct mtk_wed_pao *pao = dev->hw->wed_pao;
-+	int i;
-+
-+	for (i = 0; i < 32; i++) {
-+		dma_unmap_single(dev->hw->dev, pao->hif_txd_phys[i],
-+				 16 * PAGE_SIZE, DMA_TO_DEVICE);
-+		free_pages((unsigned long)pao->hif_txd[i], 4);
-+	}
-+
-+	return 0;
-+}
-+
-+static int
-+mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
- {
- 	struct mtk_wdma_desc *desc;
-+	void *desc_ptr;
- 	dma_addr_t desc_phys;
--	void **page_list;
-+	struct dma_page_info *page_list;
- 	u32 last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG1;
- 	int token = dev->wlan.token_start;
--	int ring_size, n_pages, page_idx;
--	int i;
--
-+	int ring_size, pkt_nums, n_pages, page_idx;
-+	int i, ret = 0;
- 
- 	if (dev->ver == MTK_WED_V1) {
- 		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
--	} else {
-+		pkt_nums = ring_size;
-+		dev->tx_buf_ring.desc_size = sizeof(struct mtk_wdma_desc);
-+	} else if (dev->hw->version == 2) {
- 		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
- 			    MTK_WED_WDMA_RING_SIZE * 2;
- 		last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG0;
-+		dev->tx_buf_ring.desc_size = sizeof(struct mtk_wdma_desc);
-+	} else if (dev->hw->version == 3) {
-+		ring_size = MTK_WED_TX_BM_DMA_SIZE;
-+		pkt_nums = MTK_WED_TX_BM_PKT_CNT;
-+		dev->tx_buf_ring.desc_size = sizeof(struct mtk_rxbm_desc);
- 	}
- 
- 	n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
-@@ -267,18 +350,20 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 	if (!page_list)
- 		return -ENOMEM;
- 
--	dev->buf_ring.size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
--	dev->buf_ring.pages = page_list;
-+	dev->tx_buf_ring.size = ring_size;
-+	dev->tx_buf_ring.pages = page_list;
-+	dev->tx_buf_ring.pkt_nums = pkt_nums;
- 
--	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
--				  &desc_phys, GFP_KERNEL);
--	if (!desc)
-+	desc_ptr = dma_alloc_coherent(dev->hw->dev,
-+				      ring_size * dev->tx_buf_ring.desc_size,
-+				      &desc_phys, GFP_KERNEL);
-+	if (!desc_ptr)
- 		return -ENOMEM;
- 
--	dev->buf_ring.desc = desc;
--	dev->buf_ring.desc_phys = desc_phys;
-+	dev->tx_buf_ring.desc = desc_ptr;
-+	dev->tx_buf_ring.desc_phys = desc_phys;
- 
--	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
-+	for (i = 0, page_idx = 0; i < pkt_nums; i += MTK_WED_BUF_PER_PAGE) {
- 		dma_addr_t page_phys, buf_phys;
- 		struct page *page;
- 		void *buf;
-@@ -295,7 +380,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 			return -ENOMEM;
- 		}
- 
--		page_list[page_idx++] = page;
-+		page_list[page_idx].addr = page;
-+		page_list[page_idx].addr_phys = page_phys;
-+		page_idx++;
-+
- 		dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
- 					DMA_BIDIRECTIONAL);
- 
-@@ -303,19 +391,23 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 		buf_phys = page_phys;
- 
- 		for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
--			u32 txd_size;
--
--			txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
--
-+			desc = desc_ptr;
- 			desc->buf0 = buf_phys;
--			desc->buf1 = buf_phys + txd_size;
--			desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
--						txd_size) |
--				     FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
--						MTK_WED_BUF_SIZE - txd_size) |
--						last_seg;
--			desc->info = 0;
--			desc++;
-+			if (dev->hw->version < 3) {
-+				u32 txd_size;
-+
-+				txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
-+				desc->buf1 = buf_phys + txd_size;
-+				desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
-+							txd_size) |
-+					     FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
-+							MTK_WED_BUF_SIZE - txd_size) |
-+							last_seg;
-+				desc->info = 0;
-+			} else {
-+				desc->ctrl = token << 16;
-+			}
-+			desc_ptr += dev->tx_buf_ring.desc_size;
- 
- 			buf += MTK_WED_BUF_SIZE;
- 			buf_phys += MTK_WED_BUF_SIZE;
-@@ -325,15 +417,18 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 					   DMA_BIDIRECTIONAL);
- 	}
- 
--	return 0;
-+	if (dev->hw->version == 3)
-+		ret = mtk_wed_pao_buffer_alloc(dev);
-+
-+	return ret;
- }
- 
- static void
--mtk_wed_free_buffer(struct mtk_wed_device *dev)
-+mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
- {
--	struct mtk_wdma_desc *desc = dev->buf_ring.desc;
--	void **page_list = dev->buf_ring.pages;
--	int ring_size, page_idx;
-+	struct mtk_rxbm_desc *desc = dev->tx_buf_ring.desc;
-+	struct dma_page_info *page_list = dev->tx_buf_ring.pages;
-+	int ring_size, page_idx, pkt_nums;
- 	int i;
- 
- 	if (!page_list)
-@@ -342,33 +437,33 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
- 	if (!desc)
- 		goto free_pagelist;
- 
--	if (dev->ver == MTK_WED_V1) {
--		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
--	} else {
--		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
--			    MTK_WED_WDMA_RING_SIZE * 2;
-+	pkt_nums = ring_size = dev->tx_buf_ring.size;
-+	if (dev->hw->version == 3) {
-+		mtk_wed_pao_free_buffer(dev);
-+		pkt_nums = dev->tx_buf_ring.pkt_nums;
- 	}
- 
--	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
--		void *page = page_list[page_idx++];
-+	for (i = 0, page_idx = 0; i < pkt_nums; i += MTK_WED_BUF_PER_PAGE) {
-+		void *page = page_list[page_idx].addr;
- 
- 		if (!page)
- 			break;
- 
--		dma_unmap_page(dev->hw->dev, desc[i].buf0,
-+		dma_unmap_page(dev->hw->dev, page_list[page_idx].addr_phys,
- 			       PAGE_SIZE, DMA_BIDIRECTIONAL);
- 		__free_page(page);
-+		page_idx++;
- 	}
- 
--	dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
--			  desc, dev->buf_ring.desc_phys);
-+	dma_free_coherent(dev->hw->dev, ring_size * dev->tx_buf_ring.desc_size,
-+			  dev->tx_buf_ring.desc, dev->tx_buf_ring.desc_phys);
- 
- free_pagelist:
- 	kfree(page_list);
- }
- 
- static int
--mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
-+mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
- {
- 	struct mtk_rxbm_desc *desc;
- 	dma_addr_t desc_phys;
-@@ -389,7 +484,7 @@ mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
- }
- 
- static void
--mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
-+mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
- {
- 	struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
- 	int ring_size = dev->rx_buf_ring.size;
-@@ -403,6 +498,113 @@ mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
- 			  desc, dev->rx_buf_ring.desc_phys);
- }
- 
-+/* TODO */
-+static int
-+mtk_wed_rx_page_buffer_alloc(struct mtk_wed_device *dev)
-+{
-+	int ring_size = dev->wlan.rx_nbuf, buf_num = MTK_WED_RX_PG_BM_CNT;
-+	struct mtk_rxbm_desc *desc;
-+	dma_addr_t desc_phys;
-+	struct dma_page_info *page_list;
-+	int n_pages, page_idx;
-+	int i;
-+
-+	n_pages = buf_num / MTK_WED_RX_PAGE_BUF_PER_PAGE;
-+
-+	page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
-+	if (!page_list)
-+		return -ENOMEM;
-+
-+	dev->rx_page_buf_ring.size = ring_size & ~(MTK_WED_BUF_PER_PAGE - 1);
-+	dev->rx_page_buf_ring.pages = page_list;
-+	dev->rx_page_buf_ring.pkt_nums = buf_num;
-+
-+	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-+	                         &desc_phys, GFP_KERNEL);
-+	if (!desc)
-+		return -ENOMEM;
-+
-+	dev->rx_page_buf_ring.desc = desc;
-+	dev->rx_page_buf_ring.desc_phys = desc_phys;
-+
-+	for (i = 0, page_idx = 0; i < buf_num; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
-+		dma_addr_t page_phys, buf_phys;
-+		struct page *page;
-+		void *buf;
-+		int s;
-+
-+		page = __dev_alloc_pages(GFP_KERNEL, 0);
-+		if (!page)
-+			return -ENOMEM;
-+
-+		page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE,
-+		                        DMA_BIDIRECTIONAL);
-+		if (dma_mapping_error(dev->hw->dev, page_phys)) {
-+			__free_page(page);
-+			return -ENOMEM;
-+		}
-+
-+		page_list[page_idx].addr= page;
-+		page_list[page_idx].addr_phys= page_phys;
-+		page_idx++;
-+
-+		dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
-+		                       DMA_BIDIRECTIONAL);
-+
-+		buf = page_to_virt(page);
-+		buf_phys = page_phys;
-+
-+		for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) {
-+
-+			desc->buf0 = cpu_to_le32(buf_phys);
-+			desc++;
-+
-+			buf += MTK_WED_PAGE_BUF_SIZE;
-+			buf_phys += MTK_WED_PAGE_BUF_SIZE;
-+		}
-+
-+		dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE,
-+					   DMA_BIDIRECTIONAL);
-+	}
-+
-+	return 0;
-+}
-+
-+static void
-+mtk_wed_rx_page_free_buffer(struct mtk_wed_device *dev)
-+{
-+	struct mtk_rxbm_desc *desc = dev->rx_page_buf_ring.desc;
-+	struct dma_page_info *page_list = dev->rx_page_buf_ring.pages;
-+	int ring_size, page_idx;
-+	int i;
-+
-+	if (!page_list)
-+		return;
-+
-+	if (!desc)
-+		goto free_pagelist;
-+
-+	ring_size = dev->rx_page_buf_ring.pkt_nums;
-+
-+	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
-+		void *page = page_list[page_idx].addr;
-+
-+		if (!page)
-+			break;
-+
-+		dma_unmap_page(dev->hw->dev, page_list[page_idx].addr_phys,
-+                              PAGE_SIZE, DMA_BIDIRECTIONAL);
-+		__free_page(page);
-+		page_idx++;
-+       }
-+
-+	dma_free_coherent(dev->hw->dev, dev->rx_page_buf_ring.size * sizeof(*desc),
-+                         desc, dev->rx_page_buf_ring.desc_phys);
-+
-+free_pagelist:
-+       kfree(page_list);
-+}
-+
- static void
- mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
- {
-@@ -416,19 +618,35 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int sca
- static void
- mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- {
--	int i;
-+	int i, scale = dev->hw->version > 1 ? 2 : 1;
- 
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
--		mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
-+		if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
-+			mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
-+
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
--		mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
-+		if ((dev->tx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
-+			mtk_wed_free_ring(dev, &dev->tx_wdma[i], scale);
- }
- 
- static void
- mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
- {
--	mtk_wed_free_rx_bm(dev);
-+	int i, scale = dev->hw->version > 1 ? 2 : 1;
-+
-+	for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++)
-+		if ((dev->rx_ring[i].flags & MTK_WED_RING_CONFIGURED))
-+			mtk_wed_free_ring(dev, &dev->rx_ring[i], 1);
-+
-+	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
-+		if ((dev->rx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
-+			mtk_wed_free_ring(dev, &dev->rx_wdma[i], scale);
-+
-+	mtk_wed_free_rx_buffer(dev);
- 	mtk_wed_free_ring(dev, &dev->rro.rro_ring, 1);
-+
-+	if (dev->wlan.hwrro)
-+		mtk_wed_rx_page_free_buffer(dev);
- }
- 
- static void
-@@ -437,7 +655,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 	u32 wdma_mask;
- 
- 	wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
--	if (dev->ver > MTK_WED_V1)
-+	if (mtk_wed_get_rx_capa(dev))
- 		wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
- 					GENMASK(1, 0));
- 	/* wed control cr set */
-@@ -447,7 +665,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 		MTK_WED_CTRL_WED_TX_BM_EN |
- 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
- 
--	if (dev->ver == MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
- 		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
- 			MTK_WED_PCIE_INT_TRIGGER_STATUS);
- 
-@@ -458,6 +676,8 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- 			MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
- 	} else {
-+		if (dev->hw->version == 3)
-+			wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN);
- 
- 		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
- 			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
-@@ -475,18 +695,20 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
- 				    dev->wlan.txfree_tbit));
- 
--		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
--			MTK_WED_WPDMA_INT_CTRL_RX0_EN |
--			MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
--			MTK_WED_WPDMA_INT_CTRL_RX1_EN |
--			MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
--			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
--				   dev->wlan.rx_tbit[0]) |
--			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
--				   dev->wlan.rx_tbit[1]));
-+		if (mtk_wed_get_rx_capa(dev))
-+			wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
-+				MTK_WED_WPDMA_INT_CTRL_RX0_EN |
-+				MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
-+				MTK_WED_WPDMA_INT_CTRL_RX1_EN |
-+				MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
-+				FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
-+					   dev->wlan.rx_tbit[0]) |
-+				FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
-+					   dev->wlan.rx_tbit[1]));
- 	}
-+
- 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
--	if (dev->ver == MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
- 		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
- 	} else {
- 		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
-@@ -506,6 +728,21 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
- {
- 	u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
- 
-+	switch (dev->hw->version) {
-+	case 1:
-+		mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
-+		break;
-+	case 2 :
-+		mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 |
-+			MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 |
-+			MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT |
-+			MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR;
-+		break;
-+	case 3:
-+		mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
-+		break;
-+	}
-+
- 	if (!dev->hw->num_flows)
- 		mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
- 
-@@ -514,31 +751,86 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
- }
- 
- static void
--mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
-+mtk_wed_pao_init(struct mtk_wed_device *dev)
- {
--	if (en) {
--		wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
--		wed_w32(dev, MTK_WED_TXP_DW1,
--			FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
--	} else {
--		wed_w32(dev, MTK_WED_TXP_DW1,
--			FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0100));
--		wed_clr(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
-+	struct mtk_wed_pao *pao = dev->hw->wed_pao;
-+	int i;
-+
-+	for (i = 0; i < 32; i++)
-+		wed_w32(dev, MTK_WED_PAO_HIFTXD_BASE_L(i),
-+			pao->hif_txd_phys[i]);
-+
-+	/* init all sta parameter */
-+	wed_w32(dev, MTK_WED_PAO_STA_INFO_INIT, MTK_WED_PAO_STA_RMVL |
-+		MTK_WED_PAO_STA_WTBL_HDRT_MODE |
-+		FIELD_PREP(MTK_WED_PAO_STA_MAX_AMSDU_LEN,
-+			   dev->wlan.max_amsdu_len >> 8) |
-+		FIELD_PREP(MTK_WED_PAO_STA_MAX_AMSDU_NUM,
-+			   dev->wlan.max_amsdu_nums));
-+
-+	wed_w32(dev, MTK_WED_PAO_STA_INFO, MTK_WED_PAO_STA_INFO_DO_INIT);
-+
-+	if (mtk_wed_poll_busy(dev, MTK_WED_PAO_STA_INFO,
-+			      MTK_WED_PAO_STA_INFO_DO_INIT)) {
-+		dev_err(dev->hw->dev, "mtk_wed%d: pao init failed!\n",
-+			dev->hw->index);
-+		return;
- 	}
-+
-+	/* init pao txd src */
-+	wed_set(dev, MTK_WED_PAO_HIFTXD_CFG,
-+		FIELD_PREP(MTK_WED_PAO_HIFTXD_SRC, dev->hw->index));
-+
-+	/* init qmem */
-+	wed_set(dev, MTK_WED_PAO_PSE, MTK_WED_PAO_PSE_RESET);
-+	if (mtk_wed_poll_busy(dev, MTK_WED_PAO_MON_QMEM_STS1, BIT(29))) {
-+		pr_info("%s: init pao qmem fail\n", __func__);
-+		return;
-+	}
-+
-+	/* eagle E1 PCIE1 tx ring 22 flow control issue */
-+	if (dev->wlan.chip_id == 0x7991) {
-+		wed_clr(dev, MTK_WED_PAO_AMSDU_FIFO,
-+			MTK_WED_PAO_AMSDU_IS_PRIOR0_RING);
-+	}
-+
-+	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+
-+	return;
- }
- 
--static void
--mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
-+static int
-+mtk_wed_hwrro_init(struct mtk_wed_device *dev)
- {
--#define MTK_WFMDA_RX_DMA_EN 	BIT(2)
-+	if (!mtk_wed_get_rx_capa(dev))
-+		return 0;
- 
-+	wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM,
-+		FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128));
-+
-+	wed_w32(dev, MTK_WED_RRO_PG_BM_BASE,
-+		dev->rx_page_buf_ring.desc_phys);
-+
-+	wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR,
-+		MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX |
-+		FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX,
-+			   MTK_WED_RX_PG_BM_CNT));
-+
-+	/* enable rx_page_bm to fetch dmad */
-+	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
-+
-+	return 0;
-+}
-+
-+static int
-+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev,
-+			   struct mtk_wed_ring *ring)
-+{
- 	int timeout = 3;
--	u32 cur_idx, regs;
-+	u32 cur_idx;
- 
- 	do {
--		regs = MTK_WED_WPDMA_RING_RX_DATA(idx) +
--		       MTK_WED_RING_OFS_CPU_IDX;
--		cur_idx = wed_r32(dev, regs);
-+		cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX);
- 		if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
- 			break;
- 
-@@ -546,70 +838,133 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
- 		timeout--;
- 	} while (timeout > 0);
- 
--	if (timeout) {
--		unsigned int val;
-+	return timeout;
-+}
- 
--		val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
--			       dev->wlan.phy_base);
--		val |= MTK_WFMDA_RX_DMA_EN;
- 
--		wifi_w32(dev, dev->wlan.wpdma_rx_glo -
--			 dev->wlan.phy_base, val);
-+static void
-+mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
-+{
-+	if (en) {
-+		wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
-+		wed_w32(dev, MTK_WED_TXP_DW1,
-+			FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
- 	} else {
--		dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
--			       dev->hw->index, idx);
-+		wed_w32(dev, MTK_WED_TXP_DW1,
-+			FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0100));
-+		wed_clr(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
- 	}
- }
- 
- static void
- mtk_wed_dma_enable(struct mtk_wed_device *dev)
- {
--	wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
--		MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+#define MTK_WFMDA_RX_DMA_EN 	BIT(2)
-+
-+	if (dev->hw->version == 1)
-+		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+			MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
- 
- 	wed_set(dev, MTK_WED_GLO_CFG,
- 		MTK_WED_GLO_CFG_TX_DMA_EN |
- 		MTK_WED_GLO_CFG_RX_DMA_EN);
-+
-+	wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+		FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) |
-+		FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8));
-+	wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+		MTK_WED_WDMA_RX_PREF_DDONE2_EN);
-+
-+	wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
-+
- 	wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- 		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
--		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-+		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN |
-+		MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR);
- 	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
- 		MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
- 
- 	wdma_set(dev, MTK_WDMA_GLO_CFG,
--		 MTK_WDMA_GLO_CFG_TX_DMA_EN |
-+		 MTK_WDMA_GLO_CFG_TX_DMA_EN /*|
- 		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
--		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
-+		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES*/);
- 
--	if (dev->ver == MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
- 		wdma_set(dev, MTK_WDMA_GLO_CFG,
- 			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
- 	} else {
- 		int idx = 0;
- 
--		wed_set(dev, MTK_WED_WPDMA_CTRL,
--			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
--
--		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
--			MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
--			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-+		if (mtk_wed_get_rx_capa(dev))
-+			wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+				MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
-+				MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
- 
- 		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
- 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
- 
-+		if (dev->hw->version == 3) {
-+			wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
-+				MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST);
-+			wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+				MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK |
-+				MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK |
-+				MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
-+
-+			wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+			//wdma_w32(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+			if (mtk_wed_get_rx_capa(dev)) {
-+				wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+					MTK_WED_WPDMA_RX_D_PREF_EN |
-+					FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) |
-+					FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8));
-+
-+				wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
-+
-+				wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+
-+				wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+			}
-+		}
-+
- 		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- 			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
- 			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
- 
-+		if (!mtk_wed_get_rx_capa(dev))
-+			return;
-+
-+		wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN);
- 		wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
- 			MTK_WED_WPDMA_RX_D_RX_DRV_EN |
- 			FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
- 			FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
- 				   0x2));
- 
--		for (idx = 0; idx < dev->hw->ring_num; idx++)
--			mtk_wed_check_wfdma_rx_fill(dev, idx);
-+		for (idx = 0; idx < dev->hw->ring_num; idx++) {
-+			struct mtk_wed_ring *ring = &dev->rx_ring[idx];
-+
-+			if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+				continue;
-+
-+			if(mtk_wed_check_wfdma_rx_fill(dev, ring)) {
-+				unsigned int val;
-+
-+				val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
-+					       dev->wlan.phy_base);
-+				val |= MTK_WFMDA_RX_DMA_EN;
-+
-+				wifi_w32(dev, dev->wlan.wpdma_rx_glo -
-+					 dev->wlan.phy_base, val);
-+
-+				dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable successful!\n",
-+						dev->hw->index, idx);
-+			} else {
-+				dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
-+					dev->hw->index, idx);
-+			}
-+		}
- 	}
- }
- 
-@@ -644,15 +999,20 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
- 			MTK_WED_WPDMA_RX_D_RX_DRV_EN);
- 		wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
- 			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
--	}
- 
--	mtk_wed_set_512_support(dev, false);
-+		if (dev->hw->version == 3 && mtk_wed_get_rx_capa(dev)) {
-+			wdma_clr(dev, MTK_WDMA_PREF_TX_CFG,
-+				 MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+			wdma_clr(dev, MTK_WDMA_PREF_RX_CFG,
-+				 MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+		}
-+	}
- }
- 
- static void
- mtk_wed_stop(struct mtk_wed_device *dev)
- {
--	if (dev->ver > MTK_WED_V1) {
-+	if (mtk_wed_get_rx_capa(dev)) {
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
- 	}
-@@ -677,13 +1037,21 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
- 		MTK_WED_CTRL_WED_TX_BM_EN |
- 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
- 
--	if (dev->hw->ver == 1)
-+	if (dev->hw->version == 1)
- 		return;
- 
- 	wed_clr(dev, MTK_WED_CTRL,
- 		MTK_WED_CTRL_RX_ROUTE_QM_EN |
- 		MTK_WED_CTRL_WED_RX_BM_EN |
- 		MTK_WED_CTRL_RX_RRO_QM_EN);
-+
-+	if (dev->hw->version == 3) {
-+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_PAO);
-+		wed_clr(dev, MTK_WED_PCIE_INT_CTRL,
-+			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
-+			MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER);
-+	}
- }
- 
- static void
-@@ -702,9 +1070,9 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- 
- 	mtk_wdma_tx_reset(dev);
- 
--	mtk_wed_free_buffer(dev);
-+	mtk_wed_free_tx_buffer(dev);
- 	mtk_wed_free_tx_rings(dev);
--	if (dev->ver > MTK_WED_V1) {
-+	if (mtk_wed_get_rx_capa(dev)) {
- 		mtk_wed_wo_reset(dev);
- 		mtk_wed_free_rx_rings(dev);
- 		mtk_wed_wo_exit(hw);
-@@ -731,24 +1099,29 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- static void
- mtk_wed_bus_init(struct mtk_wed_device *dev)
- {
--#define PCIE_BASE_ADDR0 0x11280000
-+	switch (dev->wlan.bus_type) {
-+	case MTK_WED_BUS_PCIE: {
-+		struct device_node *np = dev->hw->eth->dev->of_node;
-+		struct regmap *regs;
- 
--	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
--		struct device_node *node;
--		void __iomem * base_addr;
--		u32 value = 0;
-+		if (dev->hw->version == 2) {
-+			regs = syscon_regmap_lookup_by_phandle(np,
-+							       "mediatek,wed-pcie");
-+			if (IS_ERR(regs))
-+				break;
- 
--		node = of_parse_phandle(dev->hw->node, "mediatek,wed_pcie", 0);
--		if (!node) {
--			pr_err("%s: no wed_pcie node\n", __func__);
--			return;
-+			regmap_update_bits(regs, 0, BIT(0), BIT(0));
- 		}
- 
--		base_addr = of_iomap(node, 0);
--
--		value = readl(base_addr);
--		value |= BIT(0);
--		writel(value, base_addr);
-+		if (dev->wlan.msi) {
-+		     wed_w32(dev, MTK_WED_PCIE_CFG_INTM, dev->hw->pci_base| 0xc08);
-+		     wed_w32(dev, MTK_WED_PCIE_CFG_BASE, dev->hw->pci_base | 0xc04);
-+		     wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8));
-+		} else {
-+		     wed_w32(dev, MTK_WED_PCIE_CFG_INTM, dev->hw->pci_base | 0x180);
-+		     wed_w32(dev, MTK_WED_PCIE_CFG_BASE, dev->hw->pci_base | 0x184);
-+		     wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
-+		}
- 
- 		wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
- 			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
-@@ -756,45 +1129,53 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- 		/* pcie interrupt control: pola/source selection */
- 		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
- 			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
--			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
--		wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
--
--		value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
--		value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
--		wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
--		wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
-+			MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER |
-+			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, dev->hw->index));
- 
--		value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
--		value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
--
--		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
--		wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
--
--		/* pola setting */
--		value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
--		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
--			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
--	} else if (dev->wlan.bus_type == MTK_WED_BUS_AXI) {
-+		break;
-+	}
-+	case MTK_WED_BUS_AXI:
- 		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- 			MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
- 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
-+		break;
-+	default:
-+		break;
- 	}
-+
- 	return;
- }
- 
- static void
- mtk_wed_set_wpdma(struct mtk_wed_device *dev)
- {
--	if (dev->ver > MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
-+		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
-+	} else {
-+		mtk_wed_bus_init(dev);
-+
- 		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_int);
- 		wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK,  dev->wlan.wpdma_mask);
--		wed_w32(dev, MTK_WED_WPDMA_CFG_TX,  dev->wlan.wpdma_tx);
-+		wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
- 		wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE,  dev->wlan.wpdma_txfree);
- 
--		wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG,  dev->wlan.wpdma_rx_glo);
--		wed_w32(dev, MTK_WED_WPDMA_RX_RING,  dev->wlan.wpdma_rx);
--	} else {
--		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
-+		if (mtk_wed_get_rx_capa(dev)) {
-+			int i;
-+
-+			wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG,  dev->wlan.wpdma_rx_glo);
-+			wed_w32(dev, MTK_WED_WPDMA_RX_RING0,  dev->wlan.wpdma_rx[0]);
-+			if (dev->wlan.wpdma_rx[1])
-+				wed_w32(dev, MTK_WED_WPDMA_RX_RING1,  dev->wlan.wpdma_rx[1]);
-+
-+			if (dev->wlan.hwrro) {
-+				wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]);
-+				wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]);
-+				for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) {
-+					wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i),
-+						dev->wlan.wpdma_rx_pg + i * 0x10);
-+			       }
-+			}
-+		}
- 	}
- }
- 
-@@ -806,21 +1187,25 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
- 	mtk_wed_deinit(dev);
- 	mtk_wed_reset(dev, MTK_WED_RESET_WED);
- 
--	if (dev->ver > MTK_WED_V1)
--		mtk_wed_bus_init(dev);
--
- 	mtk_wed_set_wpdma(dev);
- 
--	mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
--	       MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
--	       MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
--	set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
--	      MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
--	      MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
-+	if (dev->hw->version == 3) {
-+		mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE;
-+		set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2);
-+	} else {
-+		mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
-+		       MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
-+		       MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-+		set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
-+		      MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
-+		      MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
-+	}
-+
- 	wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
- 
--	if (dev->ver == MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
- 		u32 offset;
-+
- 		offset = dev->hw->index ? 0x04000400 : 0;
- 		wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
- 		wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
-@@ -907,11 +1292,16 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
- 	} while (1);
- 
- 	/* configure RX_ROUTE_QM */
--	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
--	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
--	wed_set(dev, MTK_WED_RTQM_GLO_CFG,
--		FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
--	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+	if (dev->hw->version == 2) {
-+		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
-+		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-+			FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
-+		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+	} else {
-+		wed_set(dev, MTK_WED_RTQM_ENQ_CFG0,
-+			FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT, 0x3 + dev->hw->index));
-+	}
- 
- 	/* enable RX_ROUTE_QM */
- 	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
-@@ -920,23 +1310,45 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
- static void
- mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
- {
--	int size = dev->buf_ring.size;
-+	int size = dev->wlan.nbuf;
- 	int rev_size = MTK_WED_TX_RING_SIZE / 2;
--	int thr = 1;
-+	int thr_lo = 1, thr_hi = 1;
- 
--	if (dev->ver > MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
-+		wed_w32(dev, MTK_WED_TX_BM_CTRL,
-+			MTK_WED_TX_BM_CTRL_PAUSE |
-+			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
-+			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
-+	} else {
- 		size = MTK_WED_WDMA_RING_SIZE * ARRAY_SIZE(dev->tx_wdma) +
--		       dev->buf_ring.size;
-+		       dev->tx_buf_ring.size;
- 		rev_size = size;
--		thr = 0;
-+		thr_lo = 0;
-+		thr_hi = MTK_WED_TX_BM_DYN_THR_HI;
-+
-+		wed_w32(dev, MTK_WED_TX_TKID_CTRL,
-+			MTK_WED_TX_TKID_CTRL_PAUSE |
-+			FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
-+				   size / 128) |
-+			FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
-+				   size / 128));
-+
-+		/* return SKBID + SDP back to bm */
-+		if (dev->ver == 3) {
-+			wed_set(dev, MTK_WED_TX_TKID_CTRL,
-+				MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
-+			 size = dev->wlan.nbuf;
-+			 rev_size = size;
-+		} else {
-+			wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
-+				FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
-+				MTK_WED_TX_TKID_DYN_THR_HI);
-+		}
- 	}
- 
--	wed_w32(dev, MTK_WED_TX_BM_CTRL,
--		MTK_WED_TX_BM_CTRL_PAUSE |
--		FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
--		FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
-+	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
- 
--	wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
-+	wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys);
- 
- 	wed_w32(dev, MTK_WED_TX_BM_TKID,
- 		FIELD_PREP(MTK_WED_TX_BM_TKID_START,
-@@ -946,25 +1358,44 @@ mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
- 
- 	wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
- 
--	wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
--		FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr) |
--		MTK_WED_TX_BM_DYN_THR_HI);
-+	if (dev->hw->version < 3)
-+		wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
-+			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr_lo) |
-+			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr_hi));
-+	else {
-+		/* change to new bm */
-+		wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, dev->tx_buf_ring.pkt_nums |
-+			MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
-+		wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_LEGACY_EN);
-+	}
- 
--	if (dev->ver > MTK_WED_V1) {
-+	if (dev->hw->version != 1) {
- 		wed_w32(dev, MTK_WED_TX_TKID_CTRL,
- 			MTK_WED_TX_TKID_CTRL_PAUSE |
- 			FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
--				   dev->buf_ring.size / 128) |
-+				   size / 128) |
- 			FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
--				   dev->buf_ring.size / 128));
--		wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
--			FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
--			MTK_WED_TX_TKID_DYN_THR_HI);
-+				   size / 128));
-+
-+		/* return SKBID + SDP back to bm */
-+		if (dev->ver == 3)
-+			wed_set(dev, MTK_WED_TX_TKID_CTRL,
-+				MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
-+		else
-+			wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
-+				FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
-+				MTK_WED_TX_TKID_DYN_THR_HI);
- 	}
--	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
-+	wed_w32(dev, MTK_WED_TX_BM_TKID,
-+		FIELD_PREP(MTK_WED_TX_BM_TKID_START,
-+			   dev->wlan.token_start) |
-+		FIELD_PREP(MTK_WED_TX_BM_TKID_END,
-+			   dev->wlan.token_start + dev->wlan.nbuf - 1));
- 
-+	wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, dev->tx_buf_ring.pkt_nums |
-+		MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
- 	wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
--	if (dev->ver > MTK_WED_V1)
-+	if (dev->hw->version != 1)
- 		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
- }
- 
-@@ -977,7 +1408,26 @@ mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
- 
- 	wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
- 
-+	/* reset prefetch index of ring */
-+	wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
-+		MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+	wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
-+		MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+
-+	wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
-+		MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+	wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
-+		MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+
-+	/* reset prefetch FIFO of ring */
-+	wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG,
-+		MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR |
-+		MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR);
-+	wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0);
-+
- 	mtk_wed_rx_bm_hw_init(dev);
-+	if (dev->wlan.hwrro)
-+		mtk_wed_hwrro_init(dev);
- 	mtk_wed_rro_hw_init(dev);
- 	mtk_wed_route_qm_hw_init(dev);
- }
-@@ -991,7 +1441,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
- 	dev->init_done = true;
- 	mtk_wed_set_ext_int(dev, false);
- 	mtk_wed_tx_hw_init(dev);
--	if (dev->ver > MTK_WED_V1)
-+	if (mtk_wed_get_rx_capa(dev))
- 		mtk_wed_rx_hw_init(dev);
- }
- 
-@@ -1015,26 +1465,6 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
- 	}
- }
- 
--static u32
--mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
--{
-- 	if (wed_r32(dev, reg) & mask)
--		return true;
--
--	return false;
--}
--
--static int
--mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
--{
--	int sleep = 1000;
--	int timeout = 100 * sleep;
--	u32 val;
--
--	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
--				 timeout, false, dev, reg, mask);
--}
--
- static void
- mtk_wed_rx_reset(struct mtk_wed_device *dev)
- {
-@@ -1133,7 +1563,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 		mtk_wed_ring_reset(desc, MTK_WED_RX_RING_SIZE, 1, false);
- 	}
- 
--	mtk_wed_free_rx_bm(dev);
-+	mtk_wed_free_rx_buffer(dev);
- }
- 
- 
-@@ -1271,12 +1701,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
- 		int idx, int size, bool reset)
- {
- 	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
-+	int scale = dev->hw->version > 1 ? 2 : 1;
- 
- 	if(!reset)
- 		if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
--				       dev->ver, true))
-+				       scale, true))
- 			return -ENOMEM;
- 
-+	wdma->flags |= MTK_WED_RING_CONFIGURED;
-+
- 	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
- 		 wdma->desc_phys);
- 	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1296,12 +1729,33 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
- 	int idx, int size, bool reset)
- {
- 	struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
-+	int scale = dev->hw->version > 1 ? 2 : 1;
- 
- 	if (!reset)
- 		if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
--				       dev->ver, true))
-+				       scale, true))
- 			return -ENOMEM;
- 
-+	if (dev->hw->version == 3) {
-+		struct mtk_wdma_desc *desc = wdma->desc;
-+		int i;
-+
-+		for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) {
-+			desc->buf0 = 0;
-+			desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
-+			desc->buf1 = 0;
-+			desc->info = MTK_WDMA_TXD0_DESC_INFO_DMA_DONE;
-+			desc++;
-+			desc->buf0 = 0;
-+			desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
-+			desc->buf1 = 0;
-+			desc->info = MTK_WDMA_TXD1_DESC_INFO_DMA_DONE;
-+			desc++;
-+		}
-+	}
-+
-+	wdma->flags |= MTK_WED_RING_CONFIGURED;
-+
- 	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
- 		 wdma->desc_phys);
- 	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1312,7 +1766,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
- 		 MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
- 	if (reset)
- 		mtk_wed_ring_reset(wdma->desc, MTK_WED_WDMA_RING_SIZE,
--				   dev->ver, true);
-+				   scale, true);
- 	if (idx == 0)  {
- 		wed_w32(dev, MTK_WED_WDMA_RING_TX
- 			+ MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-@@ -1395,7 +1849,7 @@ mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
- {
- 	struct mtk_wed_wo *wo = dev->hw->wed_wo;
- 
--	if (dev->ver == MTK_WED_V1)
-+	if (!mtk_wed_get_rx_capa(dev))
- 		return 0;
- 
- 	return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
-@@ -1420,24 +1874,106 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
- 	}
- }
- 
-+static void
-+mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
-+{
-+	int idx, ret;
-+
-+	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
-+	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
-+
-+	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
-+		return;
-+
-+	wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+	wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+
-+	wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX,
-+		MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR |
-+		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG,
-+			   dev->wlan.rro_rx_tbit[0]) |
-+		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG,
-+			   dev->wlan.rro_rx_tbit[1]));
-+
-+	wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG,
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN |
-+		MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR |
-+		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG,
-+			   dev->wlan.rx_pg_tbit[0]) |
-+		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG,
-+			   dev->wlan.rx_pg_tbit[1])|
-+		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG,
-+			   dev->wlan.rx_pg_tbit[2]));
-+
-+	/*
-+	 * RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after
-+	 * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken
-+	 */
-+	wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+
-+	for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++) {
-+		struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
-+
-+		if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+			continue;
-+
-+		ret = mtk_wed_check_wfdma_rx_fill(dev, ring);
-+		if (!ret)
-+			dev_err(dev->hw->dev, "mtk_wed%d: rx_rro_ring(%d) init failed!\n",
-+				dev->hw->index, idx);
-+	}
-+
-+	for (idx = 0; idx < MTK_WED_RX_PAGE_QUEUES; idx++){
-+		struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
-+		if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+			continue;
-+
-+		ret = mtk_wed_check_wfdma_rx_fill(dev, ring);
-+		if (!ret)
-+			dev_err(dev->hw->dev, "mtk_wed%d: rx_page_ring(%d) init failed!\n",
-+				dev->hw->index, idx);
-+	}
-+}
-+
- static void
- mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- {
- 	int i, ret;
- 
--	if (dev->ver > MTK_WED_V1)
--		ret = mtk_wed_rx_bm_alloc(dev);
-+	if (mtk_wed_get_rx_capa(dev)) {
-+		ret = mtk_wed_rx_buffer_alloc(dev);
-+		if (ret)
-+			return;
-+
-+		if (dev->wlan.hwrro)
-+			mtk_wed_rx_page_buffer_alloc(dev);
-+	}
- 
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- 		if (!dev->tx_wdma[i].desc)
- 			mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
- 
-+	for (i = 0; i < ARRAY_SIZE(dev->rx_page_ring); i++) {
-+		u32 count = MTK_WED_RRO_MSDU_PG_CTRL0(i) +
-+			    MTK_WED_RING_OFS_COUNT;
-+
-+		if (!wed_r32(dev, count))
-+			wed_w32(dev, count, 1);
-+	}
-+
- 	mtk_wed_hw_init(dev);
- 
- 	mtk_wed_set_int(dev, irq_mask);
- 	mtk_wed_set_ext_int(dev, true);
- 
--	if (dev->ver == MTK_WED_V1) {
-+	if (dev->hw->version == 1) {
- 		u32 val;
- 
- 		val = dev->wlan.wpdma_phys |
-@@ -1448,33 +1984,52 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- 			val |= BIT(1);
- 		val |= BIT(0);
- 		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
--	} else {
-+	} else if (mtk_wed_get_rx_capa(dev)) {
- 		/* driver set mid ready and only once */
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK1,
- 			MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK2,
- 			MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
-+		if (dev->hw->version == 3)
-+			wed_w32(dev, MTK_WED_EXT_INT_MASK3,
-+				MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
- 
- 		wed_r32(dev, MTK_WED_EXT_INT_MASK1);
- 		wed_r32(dev, MTK_WED_EXT_INT_MASK2);
-+		if (dev->hw->version == 3)
-+			wed_r32(dev, MTK_WED_EXT_INT_MASK3);
- 
- 		ret = mtk_wed_rro_cfg(dev);
- 		if (ret)
- 			return;
- 	}
--	mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
-+
-+	if (dev->hw->version == 2)
-+		mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
-+	else if (dev->hw->version == 3)
-+		mtk_wed_pao_init(dev);
- 
- 	mtk_wed_dma_enable(dev);
- 	dev->running = true;
- }
- 
-+static int
-+mtk_wed_get_pci_base(struct mtk_wed_device *dev)
-+{
-+	if (dev->hw->index == 0)
-+		return MTK_WED_PCIE_BASE0;
-+	else if (dev->hw->index == 1)
-+		return MTK_WED_PCIE_BASE1;
-+	else
-+		return MTK_WED_PCIE_BASE2;
-+}
-+
- static int
- mtk_wed_attach(struct mtk_wed_device *dev)
- 	__releases(RCU)
- {
- 	struct mtk_wed_hw *hw;
- 	struct device *device;
--	u16 ver;
- 	int ret = 0;
- 
- 	RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
-@@ -1494,34 +2049,30 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 		goto out;
- 	}
- 
--	device = dev->wlan.bus_type == MTK_WED_BUS_PCIE
--	? &dev->wlan.pci_dev->dev
--	: &dev->wlan.platform_dev->dev;
-+	device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
-+				       &dev->wlan.pci_dev->dev
-+				       : &dev->wlan.platform_dev->dev;
- 	dev_info(device, "attaching wed device %d version %d\n",
--		 hw->index, hw->ver);
-+		 hw->index, hw->version);
- 
- 	dev->hw = hw;
- 	dev->dev = hw->dev;
- 	dev->irq = hw->irq;
- 	dev->wdma_idx = hw->index;
-+	dev->ver = hw->version;
-+
-+	if (dev->hw->version == 3)
-+		dev->hw->pci_base = mtk_wed_get_pci_base(dev);
- 
- 	if (hw->eth->dma_dev == hw->eth->dev &&
- 	    of_dma_is_coherent(hw->eth->dev->of_node))
- 		mtk_eth_set_dma_device(hw->eth, hw->dev);
- 
--	dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
--			    wed_r32(dev, MTK_WED_REV_ID));
--	if (dev->ver > MTK_WED_V1)
--		ver = FIELD_GET(MTK_WED_REV_ID_MINOR,
--			    wed_r32(dev, MTK_WED_REV_ID));
--
--	dev->rev_id = ((dev->ver << 28) | ver << 16);
--
--	ret = mtk_wed_buffer_alloc(dev);
-+	ret = mtk_wed_tx_buffer_alloc(dev);
- 	if (ret)
- 		goto error;
- 
--	if (dev->ver > MTK_WED_V1) {
-+	if (mtk_wed_get_rx_capa(dev)) {
- 		ret = mtk_wed_rro_alloc(dev);
- 		if (ret)
- 			goto error;
-@@ -1533,15 +2084,20 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	init_completion(&dev->wlan_reset_done);
- 	atomic_set(&dev->fe_reset, 0);
- 
--	if (dev->ver == MTK_WED_V1)
-+	if (dev->hw->version != 1)
-+		dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
-+	else
- 		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
- 				   BIT(hw->index), 0);
--	else
-+
-+	if (mtk_wed_get_rx_capa(dev))
- 		ret = mtk_wed_wo_init(hw);
- 
- error:
--	if (ret)
-+	if (ret) {
-+		pr_info("%s: detach wed\n", __func__);
- 		mtk_wed_detach(dev);
-+	}
- out:
- 	mutex_unlock(&hw_lock);
- 
-@@ -1576,8 +2132,26 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
- 	if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
- 		return -ENOMEM;
- 
-+	if (dev->hw->version == 3 && idx == 1) {
-+		/* reset prefetch index */
-+		wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+		       MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+		       MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+		wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+		       MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+		       MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+		/* reset prefetch FIFO */
-+		wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
-+		       MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
-+		       MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
-+		wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
-+	}
-+
- 	ring->reg_base = MTK_WED_RING_TX(idx);
- 	ring->wpdma = regs;
-+	ring->flags |= MTK_WED_RING_CONFIGURED;
- 
- 	/* WED -> WPDMA */
- 	wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
-@@ -1599,7 +2173,7 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
- 	struct mtk_wed_ring *ring = &dev->txfree_ring;
- 	int i, idx = 1;
- 
--	if(dev->ver > MTK_WED_V1)
-+	if(dev->hw->version > 1)
- 		idx = 0;
- 
- 	/*
-@@ -1638,6 +2212,7 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
- 
- 	ring->reg_base = MTK_WED_RING_RX_DATA(idx);
- 	ring->wpdma = regs;
-+	ring->flags |= MTK_WED_RING_CONFIGURED;
- 	dev->hw->ring_num = idx + 1;
- 
- 	/* WPDMA ->  WED */
-@@ -1652,6 +2227,129 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
- 	return 0;
- }
- 
-+static int
-+mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+{
-+	struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
-+
-+	ring->wpdma = regs;
-+
-+	wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE,
-+		readl(regs));
-+	wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT,
-+		readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+	ring->flags |= MTK_WED_RING_CONFIGURED;
-+
-+	return 0;
-+}
-+
-+static int
-+mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+{
-+	struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
-+
-+	ring->wpdma = regs;
-+
-+	wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE,
-+		readl(regs));
-+	wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT,
-+		readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+	ring->flags |= MTK_WED_RING_CONFIGURED;
-+
-+	return 0;
-+}
-+
-+static int
-+mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
-+{
-+	struct mtk_wed_ring *ring = &dev->ind_cmd_ring;
-+	u32 val = readl(regs + MTK_WED_RING_OFS_COUNT);
-+	int i = 0, cnt = 0;
-+
-+	ring->wpdma = regs;
-+
-+	if (readl(regs) & 0xf)
-+		pr_info("%s(): address is not 16-byte alignment\n", __func__);
-+
-+	wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE,
-+		readl(regs) & 0xfffffff0);
-+
-+	wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT,
-+		readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+	/* ack sn cr */
-+	wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base +
-+		dev->wlan.ind_cmd.ack_sn_addr);
-+	wed_w32(dev, MTK_WED_RRO_CFG1,
-+		FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ,
-+			   dev->wlan.ind_cmd.win_size) |
-+		FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID,
-+			   dev->wlan.ind_cmd.particular_sid));
-+
-+	/* particular session addr element */
-+	wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0, dev->wlan.ind_cmd.particular_se_phys);
-+
-+	for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) {
-+		wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA,
-+			dev->wlan.ind_cmd.addr_elem_phys[i] >> 4);
-+		wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
-+			MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f));
-+
-+		val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
-+		while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) &&
-+			 cnt < 100) {
-+			val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
-+			cnt++;
-+		}
-+		if (cnt >= 100) {
-+			dev_err(dev->hw->dev, "mtk_wed%d: write ba session base failed!\n",
-+				dev->hw->index);
-+		}
-+		/*if (mtk_wed_poll_busy(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
-+				      MTK_WED_ADDR_ELEM_TBL_WR_RDY)) {
-+			dev_err(dev->hw->dev, "mtk_wed%d: write ba session base failed!\n",
-+				dev->hw->index);
-+			return -1;
-+		}*/
-+	}
-+
-+	/* pn check init */
-+	for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) {
-+		wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M,
-+			MTK_WED_PN_CHECK_IS_FIRST);
-+
-+		wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR |
-+			FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i));
-+
-+		cnt = 0;
-+		val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
-+		while (!(val & MTK_WED_PN_CHECK_WR_RDY) &&
-+			 cnt < 100) {
-+			val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
-+			cnt++;
-+		}
-+		if (cnt >= 100) {
-+			dev_err(dev->hw->dev, "mtk_wed%d: session(%d) init failed!\n",
-+				dev->hw->index, i);
-+		}
-+		/*if (mtk_wed_poll_busy(dev, MTK_WED_PN_CHECK_CFG,
-+				      MTK_WED_PN_CHECK_WR_RDY)) {
-+			dev_err(dev->hw->dev, "mtk_wed%d: session(%d) init failed!\n",
-+				dev->hw->index, i);
-+			//return -1;
-+		}*/
-+	}
-+
-+	wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN);
-+
-+	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
-+
-+	return 0;
-+}
-+
-+
- static u32
- mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
- {
-@@ -1659,9 +2357,13 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
- 
- 	val = wed_r32(dev, MTK_WED_EXT_INT_STATUS);
- 	wed_w32(dev, MTK_WED_EXT_INT_STATUS, val);
--	val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
--	if (!dev->hw->num_flows)
--		val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
-+	if (dev->hw->version == 3) {
-+		val &= MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
-+	} else {
-+		val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;	
-+		if (!dev->hw->num_flows)
-+			val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;	
-+	}
- 	if (val && net_ratelimit())
- 		pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val);
- 
-@@ -1754,6 +2456,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 		.tx_ring_setup = mtk_wed_tx_ring_setup,
- 		.txfree_ring_setup = mtk_wed_txfree_ring_setup,
- 		.rx_ring_setup = mtk_wed_rx_ring_setup,
-+		.rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup,
-+		.msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup,
-+		.ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup,
- 		.msg_update = mtk_wed_send_msg,
- 		.start = mtk_wed_start,
- 		.stop = mtk_wed_stop,
-@@ -1765,6 +2470,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 		.detach = mtk_wed_detach,
- 		.setup_tc = mtk_wed_eth_setup_tc,
- 		.ppe_check = mtk_wed_ppe_check,
-+		.start_hwrro = mtk_wed_start_hwrro,
- 	};
- 	struct device_node *eth_np = eth->dev->of_node;
- 	struct platform_device *pdev;
-@@ -1804,9 +2510,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 	hw->wdma_phy = wdma_phy;
- 	hw->index = index;
- 	hw->irq = irq;
--	hw->ver = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
-+	hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) ?
-+		      3 : MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
- 
--	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
-+	if (hw->version == 1) {
- 		hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
- 							     "mediatek,pcie-mirror");
- 		hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
-@@ -1821,7 +2528,6 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 			regmap_write(hw->mirror, 0, 0);
- 			regmap_write(hw->mirror, 4, 0);
- 		}
--		hw->ver = MTK_WED_V1;
- 	}
- 
- 	mtk_wed_hw_add_debugfs(hw);
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 490873c..fcf7bd0 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
-@@ -10,10 +10,13 @@
- #include <linux/netdevice.h>
- #define MTK_PCIE_BASE(n)		(0x1a143000 + (n) * 0x2000)
- 
--#define MTK_WED_PKT_SIZE		1900
-+#define MTK_WED_PKT_SIZE		1920//1900
- #define MTK_WED_BUF_SIZE		2048
-+#define MTK_WED_PAGE_BUF_SIZE		128
- #define MTK_WED_BUF_PER_PAGE		(PAGE_SIZE / 2048)
-+#define MTK_WED_RX_PAGE_BUF_PER_PAGE	(PAGE_SIZE / 128)
- #define MTK_WED_RX_RING_SIZE		1536
-+#define MTK_WED_RX_PG_BM_CNT		8192
- 
- #define MTK_WED_TX_RING_SIZE		2048
- #define MTK_WED_WDMA_RING_SIZE		512
-@@ -27,6 +30,9 @@
- #define MTK_WED_RRO_QUE_CNT		8192
- #define MTK_WED_MIOD_ENTRY_CNT		128
- 
-+#define MTK_WED_TX_BM_DMA_SIZE		65536
-+#define MTK_WED_TX_BM_PKT_CNT		32768
-+
- #define MODULE_ID_WO		1
- 
- struct mtk_eth;
-@@ -43,6 +49,8 @@ struct mtk_wed_hw {
- 	struct dentry *debugfs_dir;
- 	struct mtk_wed_device *wed_dev;
- 	struct mtk_wed_wo *wed_wo;
-+	struct mtk_wed_pao *wed_pao;
-+	u32 pci_base;
- 	u32 debugfs_reg;
- 	u32 num_flows;
- 	u32 wdma_phy;
-@@ -50,7 +58,8 @@ struct mtk_wed_hw {
- 	int ring_num;
- 	int irq;
- 	int index;
--	u32 ver;
-+	int token_id;
-+	u32 version;
- };
- 
- struct mtk_wdma_info {
-@@ -58,6 +67,18 @@ struct mtk_wdma_info {
- 	u8 queue;
- 	u16 wcid;
- 	u8 bss;
-+	u32 usr_info;
-+	u8 tid;
-+	u8 is_fixedrate;
-+	u8 is_prior;
-+	u8 is_sp;
-+	u8 hf;
-+	u8 amsdu_en;
-+};
-+
-+struct mtk_wed_pao {
-+	char *hif_txd[32];
-+	dma_addr_t hif_txd_phys[32];
- };
- 
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-index 4a9e684..51e3d7c 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-@@ -11,9 +11,11 @@ struct reg_dump {
- 	u16 offset;
- 	u8 type;
- 	u8 base;
-+	u32 mask;
- };
- 
- enum {
-+	DUMP_TYPE_END,
- 	DUMP_TYPE_STRING,
- 	DUMP_TYPE_WED,
- 	DUMP_TYPE_WDMA,
-@@ -23,8 +25,11 @@ enum {
- 	DUMP_TYPE_WED_RRO,
- };
- 
-+#define DUMP_END() { .type = DUMP_TYPE_END }
- #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
- #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
-+#define DUMP_REG_MASK(_reg, _mask) { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask }
-+
- #define DUMP_RING(_prefix, _base, ...)				\
- 	{ _prefix " BASE", _base, __VA_ARGS__ },		\
- 	{ _prefix " CNT",  _base + 0x4, __VA_ARGS__ },	\
-@@ -32,6 +37,7 @@ enum {
- 	{ _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
- 
- #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
-+#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask)
- #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
- 
- #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
-@@ -52,36 +58,49 @@ print_reg_val(struct seq_file *s, const char *name, u32 val)
- 
- static void
- dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
--	      const struct reg_dump *regs, int n_regs)
-+	      const struct reg_dump **regs)
- {
--	const struct reg_dump *cur;
-+	const struct reg_dump **cur_o = regs, *cur;
-+	bool newline = false;
- 	u32 val;
- 
--	for (cur = regs; cur < &regs[n_regs]; cur++) {
--		switch (cur->type) {
--		case DUMP_TYPE_STRING:
--			seq_printf(s, "%s======== %s:\n",
--				   cur > regs ? "\n" : "",
--				   cur->name);
--			continue;
--		case DUMP_TYPE_WED:
--		case DUMP_TYPE_WED_RRO:
--			val = wed_r32(dev, cur->offset);
--			break;
--		case DUMP_TYPE_WDMA:
--			val = wdma_r32(dev, cur->offset);
--			break;
--		case DUMP_TYPE_WPDMA_TX:
--			val = wpdma_tx_r32(dev, cur->base, cur->offset);
--			break;
--		case DUMP_TYPE_WPDMA_TXFREE:
--			val = wpdma_txfree_r32(dev, cur->offset);
--			break;
--		case DUMP_TYPE_WPDMA_RX:
--			val = wpdma_rx_r32(dev, cur->base, cur->offset);
--			break;
-+	while (*cur_o) {
-+		cur = *cur_o;
-+
-+		while (cur->type != DUMP_TYPE_END) {
-+			switch (cur->type) {
-+			case DUMP_TYPE_STRING:
-+				seq_printf(s, "%s======== %s:\n",
-+					   newline ? "\n" : "",
-+					   cur->name);
-+				newline = true;
-+				cur++;
-+				continue;
-+			case DUMP_TYPE_WED:
-+			case DUMP_TYPE_WED_RRO:
-+				val = wed_r32(dev, cur->offset);
-+				break;
-+			case DUMP_TYPE_WDMA:
-+				val = wdma_r32(dev, cur->offset);
-+				break;
-+			case DUMP_TYPE_WPDMA_TX:
-+				val = wpdma_tx_r32(dev, cur->base, cur->offset);
-+				break;
-+			case DUMP_TYPE_WPDMA_TXFREE:
-+				val = wpdma_txfree_r32(dev, cur->offset);
-+				break;
-+			case DUMP_TYPE_WPDMA_RX:
-+				val = wpdma_rx_r32(dev, cur->base, cur->offset);
-+				break;
-+			}
-+
-+			if (cur->mask)
-+				val = (cur->mask & val) >> (ffs(cur->mask) - 1);
-+
-+			print_reg_val(s, cur->name, val);
-+			cur++;
- 		}
--		print_reg_val(s, cur->name, val);
-+		cur_o++;
- 	}
- }
- 
-@@ -89,7 +108,7 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
- static int
- wed_txinfo_show(struct seq_file *s, void *data)
- {
--	static const struct reg_dump regs[] = {
-+	static const struct reg_dump regs_common[] = {
- 		DUMP_STR("WED TX"),
- 		DUMP_WED(WED_TX_MIB(0)),
- 		DUMP_WED_RING(WED_RING_TX(0)),
-@@ -128,16 +147,32 @@ wed_txinfo_show(struct seq_file *s, void *data)
- 		DUMP_WDMA_RING(WDMA_RING_RX(0)),
- 		DUMP_WDMA_RING(WDMA_RING_RX(1)),
- 
--		DUMP_STR("TX FREE"),
-+		DUMP_STR("WED TX FREE"),
- 		DUMP_WED(WED_RX_MIB(0)),
-+		DUMP_WED_RING(WED_RING_RX(0)),
-+		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)),
-+
-+		DUMP_WED(WED_RX_MIB(1)),
-+		DUMP_WED_RING(WED_RING_RX(1)),
-+		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)),
-+		DUMP_STR("WED_WPDMA TX FREE"),
-+		DUMP_WED_RING(WED_WPDMA_RING_RX(0)),
-+		DUMP_WED_RING(WED_WPDMA_RING_RX(1)),
-+		DUMP_END(),
-+	};
-+
-+	static const struct reg_dump *regs[] = {
-+		&regs_common[0],
-+		NULL,
- 	};
-+
- 	struct mtk_wed_hw *hw = s->private;
- 	struct mtk_wed_device *dev = hw->wed_dev;
- 
- 	if (!dev)
- 		return 0;
- 
--	dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
-+	dump_wed_regs(s, dev, regs);
- 
- 	return 0;
- }
-@@ -146,7 +181,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
- static int
- wed_rxinfo_show(struct seq_file *s, void *data)
- {
--	static const struct reg_dump regs[] = {
-+	static const struct reg_dump regs_common[] = {
- 		DUMP_STR("WPDMA RX"),
- 		DUMP_WPDMA_RX_RING(0),
- 		DUMP_WPDMA_RX_RING(1),
-@@ -164,7 +199,7 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- 		DUMP_WED_RING(WED_RING_RX_DATA(0)),
- 		DUMP_WED_RING(WED_RING_RX_DATA(1)),
- 
--		DUMP_STR("WED RRO"),
-+		DUMP_STR("WED WO RRO"),
- 		DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
- 		DUMP_WED(WED_RROQM_MID_MIB),
- 		DUMP_WED(WED_RROQM_MOD_MIB),
-@@ -175,16 +210,6 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- 		DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
- 		DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
- 
--		DUMP_STR("WED Route QM"),
--		DUMP_WED(WED_RTQM_R2H_MIB(0)),
--		DUMP_WED(WED_RTQM_R2Q_MIB(0)),
--		DUMP_WED(WED_RTQM_Q2H_MIB(0)),
--		DUMP_WED(WED_RTQM_R2H_MIB(1)),
--		DUMP_WED(WED_RTQM_R2Q_MIB(1)),
--		DUMP_WED(WED_RTQM_Q2H_MIB(1)),
--		DUMP_WED(WED_RTQM_Q2N_MIB),
--		DUMP_WED(WED_RTQM_Q2B_MIB),
--		DUMP_WED(WED_RTQM_PFDBK_MIB),
- 
- 		DUMP_STR("WED WDMA TX"),
- 		DUMP_WED(WED_WDMA_TX_MIB),
-@@ -205,15 +230,99 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- 		DUMP_WED(WED_RX_BM_INTF2),
- 		DUMP_WED(WED_RX_BM_INTF),
- 		DUMP_WED(WED_RX_BM_ERR_STS),
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump regs_v2[] = {
-+		DUMP_STR("WED Route QM"),
-+		DUMP_WED(WED_RTQM_R2H_MIB(0)),
-+		DUMP_WED(WED_RTQM_R2Q_MIB(0)),
-+		DUMP_WED(WED_RTQM_Q2H_MIB(0)),
-+		DUMP_WED(WED_RTQM_R2H_MIB(1)),
-+		DUMP_WED(WED_RTQM_R2Q_MIB(1)),
-+		DUMP_WED(WED_RTQM_Q2H_MIB(1)),
-+		DUMP_WED(WED_RTQM_Q2N_MIB),
-+		DUMP_WED(WED_RTQM_Q2B_MIB),
-+		DUMP_WED(WED_RTQM_PFDBK_MIB),
-+
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump regs_v3[] = {
-+		DUMP_STR("WED RX RRO DATA"),
-+		DUMP_WED_RING(WED_RRO_RX_D_RX(0)),
-+		DUMP_WED_RING(WED_RRO_RX_D_RX(1)),
-+
-+		DUMP_STR("WED RX MSDU PAGE"),
-+		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)),
-+		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)),
-+		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)),
-+
-+		DUMP_STR("WED RX IND CMD"),
-+		DUMP_WED(WED_IND_CMD_RX_CTRL1),
-+		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT),
-+		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX),
-+		DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX),
-+		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT),
-+		DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT),
-+		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0,
-+			      WED_IND_CMD_PREFETCH_FREE_CNT),
-+		DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID),
-+
-+		DUMP_STR("WED ADDR ELEM"),
-+		DUMP_WED(WED_ADDR_ELEM_CFG0),
-+		DUMP_WED_MASK(WED_ADDR_ELEM_CFG1,
-+			      WED_ADDR_ELEM_PREFETCH_FREE_CNT),
-+
-+		DUMP_STR("WED Route QM"),
-+		DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT),
-+		DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT),
-+		DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT),
-+		DUMP_WED(WED_RTQM_ENQ_ERR_CNT),
-+
-+		DUMP_WED(WED_RTQM_DEQ_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_DEQ_PKT_CNT),
-+		DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT),
-+		DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT),
-+		DUMP_WED(WED_RTQM_DEQ_ERR_CNT),
-+
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump *regs_new_v2[] = {
-+		&regs_common[0],
-+		&regs_v2[0],
-+		NULL,
-+	};
-+
-+	static const struct reg_dump *regs_new_v3[] = {
-+		&regs_common[0],
-+		&regs_v3[0],
-+		NULL,
- 	};
- 
- 	struct mtk_wed_hw *hw = s->private;
- 	struct mtk_wed_device *dev = hw->wed_dev;
-+	const struct reg_dump **regs;
- 
- 	if (!dev)
- 		return 0;
- 
--	dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
-+	switch(dev->hw->version) {
-+	case 2:
-+		regs = regs_new_v2;
-+		break;
-+	case 3:
-+		regs = regs_new_v3;
-+		break;
-+	default:
-+		return 0;
-+	}
-+
-+	dump_wed_regs(s, dev, regs);
- 
- 	return 0;
- }
-@@ -248,6 +357,383 @@ mtk_wed_reg_get(void *data, u64 *val)
- DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
-              "0x%08llx\n");
- 
-+static int
-+wed_token_txd_show(struct seq_file *s, void *data)
-+{
-+	struct mtk_wed_hw *hw = s->private;
-+	struct mtk_wed_device *dev = hw->wed_dev;
-+	struct dma_page_info *page_list = dev->tx_buf_ring.pages;
-+	int token = dev->wlan.token_start;
-+	u32 val = hw->token_id, size = 1;
-+	int page_idx = (val - token) / 2;
-+	int i;
-+
-+	if (val < token) {
-+		size = val;
-+		page_idx = 0;
-+	}
-+
-+	for (i = 0; i < size; i += MTK_WED_BUF_PER_PAGE) {
-+		void *page = page_list[page_idx++].addr;
-+		void *buf;
-+		int j;
-+
-+		if (!page)
-+			break;
-+
-+		buf = page_to_virt(page);
-+
-+		for (j = 0; j < MTK_WED_BUF_PER_PAGE; j++) {
-+			printk("[TXD]:token id = %d\n", token + 2 * (page_idx - 1) + j);
-+			print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, (u8 *)buf, 128, false);
-+			seq_printf(s, "\n");
-+
-+			buf += MTK_WED_BUF_SIZE;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+DEFINE_SHOW_ATTRIBUTE(wed_token_txd);
-+
-+static int
-+wed_pao_show(struct seq_file *s, void *data)
-+{
-+	static const struct reg_dump regs_common[] = {
-+		DUMP_STR("PAO AMDSU INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_FIFO_DMAD),
-+
-+		DUMP_STR("PAO AMDSU ENG0 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(0)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(0)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(0)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(0)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(0)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(0),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(0),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG1 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(1)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(1)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(1)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(1)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(1)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(1),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(1),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(1),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG2 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(2)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(2)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(2)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(2)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(2)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(2),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(2),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG3 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(3)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(3)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(3)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(3)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(3)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(3),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(3),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG4 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(4)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(4)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(4)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(4)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(4)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(4),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(4),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG5 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(5)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(5)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(5)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(5)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(5)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(5),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(5),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG6 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(6)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(6)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(6)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(6)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(6)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(6),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(6),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG7 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(7)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(7)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(7)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(7)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(7)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(7),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(7),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(7),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(7),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO AMDSU ENG8 INFO"),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(8)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(8)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(8)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(8)),
-+		DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(8)),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(8),
-+			      WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(8),
-+			      WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+			      WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+			      WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+		DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+			      WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+		DUMP_STR("PAO QMEM INFO"),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(0), WED_PAO_QMEM_FQ_CNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(0), WED_PAO_QMEM_SP_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(1), WED_PAO_QMEM_TID0_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(1), WED_PAO_QMEM_TID1_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(2), WED_PAO_QMEM_TID2_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(2), WED_PAO_QMEM_TID3_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(3), WED_PAO_QMEM_TID4_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(3), WED_PAO_QMEM_TID5_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(4), WED_PAO_QMEM_TID6_QCNT),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(4), WED_PAO_QMEM_TID7_QCNT),
-+
-+
-+		DUMP_STR("PAO QMEM HEAD INFO"),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(0), WED_PAO_QMEM_FQ_HEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(0), WED_PAO_QMEM_SP_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(1), WED_PAO_QMEM_TID0_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(1), WED_PAO_QMEM_TID1_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(2), WED_PAO_QMEM_TID2_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(2), WED_PAO_QMEM_TID3_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(3), WED_PAO_QMEM_TID4_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(3), WED_PAO_QMEM_TID5_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(4), WED_PAO_QMEM_TID6_QHEAD),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(4), WED_PAO_QMEM_TID7_QHEAD),
-+
-+		DUMP_STR("PAO QMEM TAIL INFO"),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(5), WED_PAO_QMEM_FQ_TAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(5), WED_PAO_QMEM_SP_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(6), WED_PAO_QMEM_TID0_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(6), WED_PAO_QMEM_TID1_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(7), WED_PAO_QMEM_TID2_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(7), WED_PAO_QMEM_TID3_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(8), WED_PAO_QMEM_TID4_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(8), WED_PAO_QMEM_TID5_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(9), WED_PAO_QMEM_TID6_QTAIL),
-+		DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(9), WED_PAO_QMEM_TID7_QTAIL),
-+
-+		DUMP_STR("PAO HIFTXD MSDU INFO"),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(1)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(2)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(3)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(4)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(5)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(6)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(7)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(8)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(9)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(10)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(11)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(12)),
-+		DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(13)),
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump *regs[] = {
-+		&regs_common[0],
-+		NULL,
-+	};
-+	struct mtk_wed_hw *hw = s->private;
-+	struct mtk_wed_device *dev = hw->wed_dev;
-+
-+	if (!dev)
-+		return 0;
-+
-+	dump_wed_regs(s, dev, regs);
-+
-+	return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_pao);
-+
-+static int
-+wed_rtqm_show(struct seq_file *s, void *data)
-+{
-+	static const struct reg_dump regs_common[] = {
-+		DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"),
-+		DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT),
-+		DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT),
-+
-+
-+		DUMP_STR("WED Route QM IGRS1(Legacy)"),
-+		DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT),
-+		DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT),
-+
-+		DUMP_STR("WED Route QM IGRS2(RRO3.0)"),
-+		DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT),
-+		DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT),
-+
-+		DUMP_STR("WED Route QM IGRS3(DEBUG)"),
-+		DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
-+		DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT),
-+		DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)),
-+		DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)),
-+		DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT),
-+
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump *regs[] = {
-+		&regs_common[0],
-+		NULL,
-+	};
-+	struct mtk_wed_hw *hw = s->private;
-+	struct mtk_wed_device *dev = hw->wed_dev;
-+
-+	if (!dev)
-+		return 0;
-+
-+	dump_wed_regs(s, dev, regs);
-+
-+	return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_rtqm);
-+
-+
-+static int
-+wed_rro_show(struct seq_file *s, void *data)
-+{
-+	static const struct reg_dump regs_common[] = {
-+		DUMP_STR("RRO/IND CMD CNT"),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(1)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(2)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(3)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(4)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(5)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(6)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(7)),
-+		DUMP_WED(WED_RX_IND_CMD_CNT(8)),
-+		DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9),
-+			      WED_IND_CMD_MAGIC_CNT_FAIL_CNT),
-+
-+		DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)),
-+		DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1),
-+			      WED_ADDR_ELEM_SIG_FAIL_CNT),
-+		DUMP_WED(WED_RX_MSDU_PG_CNT(1)),
-+		DUMP_WED(WED_RX_MSDU_PG_CNT(2)),
-+		DUMP_WED(WED_RX_MSDU_PG_CNT(3)),
-+		DUMP_WED(WED_RX_MSDU_PG_CNT(4)),
-+		DUMP_WED(WED_RX_MSDU_PG_CNT(5)),
-+		DUMP_WED_MASK(WED_RX_PN_CHK_CNT,
-+			      WED_PN_CHK_FAIL_CNT),
-+
-+		DUMP_END()
-+	};
-+
-+	static const struct reg_dump *regs[] = {
-+		&regs_common[0],
-+		NULL,
-+	};
-+	struct mtk_wed_hw *hw = s->private;
-+	struct mtk_wed_device *dev = hw->wed_dev;
-+
-+	if (!dev)
-+		return 0;
-+
-+	dump_wed_regs(s, dev, regs);
-+
-+	return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_rro);
-+
- void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
- {
- 	struct dentry *dir;
-@@ -261,8 +747,18 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
- 	debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
- 	debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
- 	debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
--	debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
--	if (hw->ver != MTK_WED_V1) {
-+	debugfs_create_u32("token_id", 0600, dir, &hw->token_id);
-+	debugfs_create_file_unsafe("token_txd", 0600, dir, hw, &wed_token_txd_fops);
-+
-+	if (hw->version == 3)
-+		debugfs_create_file_unsafe("pao", 0400, dir, hw, &wed_pao_fops);
-+
-+	if (hw->version != 1) {
-+		debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
-+		if (hw->version == 3) {
-+			debugfs_create_file_unsafe("rtqm", 0400, dir, hw, &wed_rtqm_fops);
-+			debugfs_create_file_unsafe("rro", 0400, dir, hw, &wed_rro_fops);
-+		}
- 		wed_wo_mcu_debugfs(hw, dir);
- 	}
- }
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-index b5a86f6..c2d060b 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -245,8 +245,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
- 	if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed"))
- 		mcu = MT7981_FIRMWARE_WO;
- 	else
--		mcu = wo->hw->index ? MT7986_FIRMWARE_WO_2 :
--				      MT7986_FIRMWARE_WO_1;
-+		mcu = wo->hw->index ? MTK_FIRMWARE_WO_1 : MTK_FIRMWARE_WO_0;
- 
- 	ret = request_firmware(&fw, mcu, wo->hw->dev);
- 	if (ret)
-@@ -293,8 +292,12 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
- 	}
- 
- 	/* write the start address */
--	boot_cr = wo->hw->index ?
--		WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+	if (wo->hw->version == 3)
-+		boot_cr = WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+	else
-+		boot_cr = wo->hw->index ?
-+			WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+
- 	wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
- 
- 	/* wo firmware reset */
-@@ -302,8 +305,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
- 
- 	val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
- 
--	val |= wo->hw->index ? WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK :
--		WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
-+	val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
- 
- 	wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-index dbb17ae..a533b6e 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-@@ -17,8 +17,9 @@
- #define WARP_ALREADY_DONE_STATUS (1)
- 
- #define MT7981_FIRMWARE_WO		"mediatek/mt7981_wo.bin"
--#define MT7986_FIRMWARE_WO_1		"mediatek/mt7986_wo_0.bin"
--#define MT7986_FIRMWARE_WO_2		"mediatek/mt7986_wo_1.bin"
-+#define MTK_FIRMWARE_WO_0		"mediatek/mtk_wo_0.bin"
-+#define MTK_FIRMWARE_WO_1		"mediatek/mtk_wo_1.bin"
-+#define MTK_FIRMWARE_WO_2		"mediatek/mtk_wo_2.bin"
- 
- #define WOCPU_EMI_DEV_NODE		"mediatek,wocpu_emi"
- #define WOCPU_ILM_DEV_NODE		"mediatek,wocpu_ilm"
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 403a36b..25be547 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -20,6 +20,9 @@
- #define MTK_WDMA_DESC_CTRL_DMA_DONE		BIT(31)
- #define MTK_WED_RX_BM_TOKEN			GENMASK(31, 16)
- 
-+#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE	BIT(29)
-+#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE	BIT(31)
-+
- struct mtk_wdma_desc {
- 	__le32 buf0;
- 	__le32 ctrl;
-@@ -51,6 +54,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_RESET_WDMA_INT_AGENT			BIT(19)
- #define MTK_WED_RESET_RX_RRO_QM				BIT(20)
- #define MTK_WED_RESET_RX_ROUTE_QM			BIT(21)
-+#define MTK_WED_RESET_TX_PAO				BIT(22)
- #define MTK_WED_RESET_WED				BIT(31)
- 
- #define MTK_WED_CTRL					0x00c
-@@ -58,6 +62,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY		BIT(1)
- #define MTK_WED_CTRL_WDMA_INT_AGENT_EN			BIT(2)
- #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY		BIT(3)
-+#define MTK_WED_CTRL_WED_RX_IND_CMD_EN			BIT(5)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_EN			BIT(6)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU			BIT(7)
- #define MTK_WED_CTRL_WED_TX_BM_EN			BIT(8)
- #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
- #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
-@@ -68,9 +75,14 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_RX_RRO_QM_BUSY			BIT(15)
- #define MTK_WED_CTRL_RX_ROUTE_QM_EN			BIT(16)
- #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY			BIT(17)
-+#define MTK_WED_CTRL_TX_TKID_ALI_EN			BIT(20)
-+#define MTK_WED_CTRL_TX_TKID_ALI_BUSY			BIT(21)
-+#define MTK_WED_CTRL_TX_PAO_EN				BIT(22)
-+#define MTK_WED_CTRL_TX_PAO_BUSY			BIT(23)
- #define MTK_WED_CTRL_FINAL_DIDX_READ			BIT(24)
- #define MTK_WED_CTRL_ETH_DMAD_FMT			BIT(25)
- #define MTK_WED_CTRL_MIB_READ_CLEAR			BIT(28)
-+#define MTK_WED_CTRL_FLD_MIB_RD_CLR			BIT(28)
- 
- #define MTK_WED_EXT_INT_STATUS				0x020
- #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR		BIT(0)
-@@ -78,12 +90,10 @@ struct mtk_wdma_desc {
- #define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID	BIT(4)
- #define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH		BIT(8)
- #define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH		BIT(9)
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
--#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH		BIT(10)
--#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH		BIT(11)
--#endif
--#define MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY		BIT(12)
--#define MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER		BIT(13)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2		BIT(10)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2		BIT(11)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH		BIT(12)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH		BIT(13)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR	BIT(16)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR	BIT(17)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT		BIT(18)
-@@ -100,17 +110,15 @@ struct mtk_wdma_desc {
- #define MTK_WED_EXT_INT_STATUS_ERROR_MASK		(MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
- 							 MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
- 							 MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
--							 MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY | \
--							 MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER | \
- 							 MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
- 							 MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
- 							 MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
--							 MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR | \
--							 MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
-+							 MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR)
- 
- #define MTK_WED_EXT_INT_MASK				0x028
- #define MTK_WED_EXT_INT_MASK1				0x02c
- #define MTK_WED_EXT_INT_MASK2				0x030
-+#define MTK_WED_EXT_INT_MASK3				0x034
- 
- #define MTK_WED_STATUS					0x060
- #define MTK_WED_STATUS_TX				GENMASK(15, 8)
-@@ -118,9 +126,14 @@ struct mtk_wdma_desc {
- #define MTK_WED_TX_BM_CTRL				0x080
- #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM			GENMASK(6, 0)
- #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM			GENMASK(22, 16)
-+#define MTK_WED_TX_BM_CTRL_LEGACY_EN			BIT(26)
-+#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT		BIT(27)
- #define MTK_WED_TX_BM_CTRL_PAUSE			BIT(28)
- 
- #define MTK_WED_TX_BM_BASE				0x084
-+#define MTK_WED_TX_BM_INIT_PTR				0x088
-+#define MTK_WED_TX_BM_SW_TAIL_IDX			GENMASK(16, 0)
-+#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX			BIT(16)
- 
- #define MTK_WED_TX_BM_BUF_LEN				0x08c
- 
-@@ -134,22 +147,24 @@ struct mtk_wdma_desc {
- #if defined(CONFIG_MEDIATEK_NETSYS_V2)
- #define MTK_WED_TX_BM_DYN_THR_LO			GENMASK(8, 0)
- #define MTK_WED_TX_BM_DYN_THR_HI			GENMASK(24, 16)
--
--#define MTK_WED_TX_BM_TKID				0x0c8
--#define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
--#define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
- #else
- #define MTK_WED_TX_BM_DYN_THR_LO			GENMASK(6, 0)
- #define MTK_WED_TX_BM_DYN_THR_HI			GENMASK(22, 16)
-+#endif
- 
--#define MTK_WED_TX_BM_TKID				0x088
-+#define MTK_WED_TX_BM_TKID				0x0c8
- #define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
- #define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
--#endif
- 
- #define MTK_WED_TX_TKID_CTRL				0x0c0
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM		GENMASK(7, 0)
-+#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM		GENMASK(23, 16)
-+#else
- #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM		GENMASK(6, 0)
- #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM		GENMASK(22, 16)
-+#endif
-+
- #define MTK_WED_TX_TKID_CTRL_PAUSE			BIT(28)
- 
- #define MTK_WED_TX_TKID_DYN_THR				0x0e0
-@@ -220,12 +235,15 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC	BIT(5)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC	BIT(6)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC	BIT(7)
--#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER	GENMASK(18, 16)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER	GENMASK(15, 12)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4	BIT(18)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT	BIT(19)
--#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK	BIT(20)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR		BIT(21)
- #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP		BIT(24)
-+#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST		BIT(25)
- #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV		BIT(28)
-+#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK		BIT(30)
- 
- /* CONFIG_MEDIATEK_NETSYS_V1 */
- #define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE		GENMASK(5, 4)
-@@ -288,9 +306,11 @@ struct mtk_wdma_desc {
- #define MTK_WED_PCIE_INT_TRIGGER_STATUS			BIT(16)
- 
- #define MTK_WED_PCIE_INT_CTRL				0x57c
--#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA		BIT(20)
--#define MTK_WED_PCIE_INT_CTRL_SRC_SEL			GENMASK(17, 16)
- #define MTK_WED_PCIE_INT_CTRL_POLL_EN 			GENMASK(13, 12)
-+#define MTK_WED_PCIE_INT_CTRL_SRC_SEL			GENMASK(17, 16)
-+#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA		BIT(20)
-+#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER		BIT(21)
-+
- #define MTK_WED_WPDMA_CFG_BASE				0x580
- #define MTK_WED_WPDMA_CFG_INT_MASK			0x584
- #define MTK_WED_WPDMA_CFG_TX				0x588
-@@ -319,20 +339,50 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX			GENMASK(25, 24)
- 
- #define MTK_WED_WPDMA_RX_GLO_CFG			0x76c
--#define MTK_WED_WPDMA_RX_RING				0x770
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_WPDMA_RX_RING0				0x770
-+#else
-+#define MTK_WED_WPDMA_RX_RING0				0x7d0
-+#endif
-+#define MTK_WED_WPDMA_RX_RING1				0x7d8
- 
- #define MTK_WED_WPDMA_RX_D_MIB(_n)			(0x774 + (_n) * 4)
- #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n)		(0x784 + (_n) * 4)
- #define MTK_WED_WPDMA_RX_D_COHERENT_MIB			0x78c
- 
-+#define MTK_WED_WPDMA_RX_D_PREF_CFG			0x7b4
-+#define MTK_WED_WPDMA_RX_D_PREF_EN			BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE		GENMASK(12, 8)
-+#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES		GENMASK(21, 16)
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX		0x7b8
-+#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR		BIT(15)
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX		0x7bc
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG		0x7c0
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR		BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR		BIT(16)
-+
- #define MTK_WED_WDMA_RING_TX				0x800
- 
- #define MTK_WED_WDMA_TX_MIB				0x810
- 
--
- #define MTK_WED_WDMA_RING_RX(_n)			(0x900 + (_n) * 0x10)
- #define MTK_WED_WDMA_RX_THRES(_n)			(0x940 + (_n) * 0x4)
- 
-+#define MTK_WED_WDMA_RX_PREF_CFG			0x950
-+#define MTK_WED_WDMA_RX_PREF_EN				BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_BURST_SIZE			GENMASK(12, 8)
-+#define MTK_WED_WDMA_RX_PREF_LOW_THRES			GENMASK(21, 16)
-+#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR		BIT(24)
-+#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR		BIT(25)
-+#define MTK_WED_WDMA_RX_PREF_DDONE2_EN			BIT(26)
-+
-+#define MTK_WED_WDMA_RX_PREF_FIFO_CFG			0x95C
-+#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR		BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR		BIT(16)
-+
- #define MTK_WED_WDMA_GLO_CFG				0xa04
- #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN			BIT(0)
- #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK		BIT(1)
-@@ -365,6 +415,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE		GENMASK(17, 16)
- 
- #define MTK_WED_WDMA_INT_CTRL				0xa2c
-+#define MTK_WED_WDMA_INT_POLL_PRD			GENMASK(7, 0)
- #define MTK_WED_WDMA_INT_POLL_SRC_SEL			GENMASK(17, 16)
- 
- #define MTK_WED_WDMA_CFG_BASE				0xaa0
-@@ -426,6 +477,18 @@ struct mtk_wdma_desc {
- #define MTK_WDMA_INT_GRP1				0x250
- #define MTK_WDMA_INT_GRP2				0x254
- 
-+#define MTK_WDMA_PREF_TX_CFG				0x2d0
-+#define MTK_WDMA_PREF_TX_CFG_PREF_EN			BIT(0)
-+
-+#define MTK_WDMA_PREF_RX_CFG				0x2dc
-+#define MTK_WDMA_PREF_RX_CFG_PREF_EN			BIT(0)
-+
-+#define MTK_WDMA_WRBK_TX_CFG				0x300
-+#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN			BIT(30)
-+
-+#define MTK_WDMA_WRBK_RX_CFG				0x344
-+#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN			BIT(30)
-+
- #define MTK_PCIE_MIRROR_MAP(n)				((n) ? 0x4 : 0x0)
- #define MTK_PCIE_MIRROR_MAP_EN				BIT(0)
- #define MTK_PCIE_MIRROR_MAP_WED_ID			BIT(1)
-@@ -439,6 +502,31 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q_DBG_BYPASS			BIT(5)
- #define MTK_WED_RTQM_TXDMAD_FPORT			GENMASK(23, 20)
- 
-+#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT		0xb1c
-+#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n)		(0xb20 + (_n) * 0x4)
-+#define	MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT			0xb28
-+#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n)		(0xb2c + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS0_FDROP_CNT			0xb34
-+
-+
-+#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT		0xb44
-+#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n)		(0xb48 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT			0xb50
-+#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n)		(0xb54+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS1_FDROP_CNT			0xb5c
-+
-+#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT		0xb6c
-+#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n)		(0xb70 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT			0xb78
-+#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n)		(0xb7c+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS2_FDROP_CNT			0xb84
-+
-+#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT		0xb94
-+#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n)		(0xb98 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT			0xba0
-+#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n)		(0xba4+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS3_FDROP_CNT			0xbac
-+
- #define MTK_WED_RTQM_R2H_MIB(_n)			(0xb70 + (_n) * 0x4)
- #define MTK_WED_RTQM_R2Q_MIB(_n)			(0xb78 + (_n) * 0x4)
- #define MTK_WED_RTQM_Q2N_MIB				0xb80
-@@ -447,6 +535,24 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q2B_MIB				0xb8c
- #define MTK_WED_RTQM_PFDBK_MIB				0xb90
- 
-+#define MTK_WED_RTQM_ENQ_CFG0				0xbb8
-+#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT		GENMASK(15, 12)
-+
-+#define MTK_WED_RTQM_FDROP_MIB				0xb84
-+#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT			0xbbc
-+#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT			0xbc0
-+#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT			0xbc4
-+#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT			0xbc8
-+#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT			0xbcc
-+#define MTK_WED_RTQM_ENQ_ERR_CNT			0xbd0
-+
-+#define MTK_WED_RTQM_DEQ_DMAD_CNT			0xbd8
-+#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT			0xbdc
-+#define MTK_WED_RTQM_DEQ_PKT_CNT			0xbe0
-+#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT			0xbe4
-+#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT			0xbe8
-+#define MTK_WED_RTQM_DEQ_ERR_CNT			0xbec
-+
- #define MTK_WED_RROQM_GLO_CFG				0xc04
- #define MTK_WED_RROQM_RST_IDX				0xc08
- #define MTK_WED_RROQM_RST_IDX_MIOD 			BIT(0)
-@@ -487,8 +593,8 @@ struct mtk_wdma_desc {
- #define MTK_WED_RX_BM_BASE				0xd84
- #define MTK_WED_RX_BM_INIT_PTR				0xd88
- #define MTK_WED_RX_BM_PTR	      			0xd8c
--#define MTK_WED_RX_BM_PTR_HEAD				GENMASK(32, 16)
- #define MTK_WED_RX_BM_PTR_TAIL				GENMASK(15, 0)
-+#define MTK_WED_RX_BM_PTR_HEAD				GENMASK(32, 16)
- 
- #define MTK_WED_RX_BM_BLEN	      			0xd90
- #define MTK_WED_RX_BM_STS				0xd94
-@@ -496,7 +602,193 @@ struct mtk_wdma_desc {
- #define MTK_WED_RX_BM_INTF				0xd9c
- #define MTK_WED_RX_BM_ERR_STS				0xda8
- 
-+#define MTK_RRO_IND_CMD_SIGNATURE			0xe00
-+#define MTK_RRO_IND_CMD_DMA_IDX				GENMASK(11, 0)
-+#define MTK_RRO_IND_CMD_MAGIC_CNT			GENMASK(30, 28)
-+
-+#define MTK_WED_IND_CMD_RX_CTRL0			0xe04
-+#define MTK_WED_IND_CMD_PROC_IDX			GENMASK(11, 0)
-+#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT		GENMASK(19, 16)
-+#define MTK_WED_IND_CMD_MAGIC_CNT			GENMASK(30, 28)
-+
-+#define MTK_WED_IND_CMD_RX_CTRL1			0xe08
-+#define MTK_WED_IND_CMD_RX_CTRL2			0xe0c
-+#define MTK_WED_IND_CMD_MAX_CNT				GENMASK(11, 0)
-+#define MTK_WED_IND_CMD_BASE_M				GENMASK(19, 16)
-+
-+#define MTK_WED_RRO_CFG0				0xe10
-+#define MTK_WED_RRO_CFG1				0xe14
-+#define MTK_WED_RRO_CFG1_MAX_WIN_SZ			GENMASK(31, 29)
-+#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M			GENMASK(19, 16)
-+#define MTK_WED_RRO_CFG1_PARTICL_SE_ID			GENMASK(11, 0)
-+
-+#define MTK_WED_ADDR_ELEM_CFG0				0xe18
-+#define MTK_WED_ADDR_ELEM_CFG1				0xe1c
-+#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT		GENMASK(19, 16)
-+
-+#define MTK_WED_ADDR_ELEM_TBL_CFG 			0xe20
-+#define MTK_WED_ADDR_ELEM_TBL_OFFSET			GENMASK(6, 0)
-+#define MTK_WED_ADDR_ELEM_TBL_RD_RDY			BIT(28)
-+#define MTK_WED_ADDR_ELEM_TBL_WR_RDY			BIT(29)
-+#define MTK_WED_ADDR_ELEM_TBL_RD			BIT(30)
-+#define MTK_WED_ADDR_ELEM_TBL_WR			BIT(31)
-+
-+#define MTK_WED_RADDR_ELEM_TBL_WDATA 			0xe24
-+#define MTK_WED_RADDR_ELEM_TBL_RDATA 			0xe28
-+
-+#define MTK_WED_PN_CHECK_CFG 				0xe30
-+#define MTK_WED_PN_CHECK_SE_ID				GENMASK(11, 0)
-+#define MTK_WED_PN_CHECK_RD_RDY				BIT(28)
-+#define MTK_WED_PN_CHECK_WR_RDY				BIT(29)
-+#define MTK_WED_PN_CHECK_RD				BIT(30)
-+#define MTK_WED_PN_CHECK_WR				BIT(31)
-+
-+#define MTK_WED_PN_CHECK_WDATA_M 			0xe38
-+#define MTK_WED_PN_CHECK_IS_FIRST			BIT(17)
-+
-+#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n)		(0xe44 + (_n) * 0x8)
-+
-+#define MTK_WED_RRO_MSDU_PG_RING2_CFG			0xe58
-+#define MTK_WED_RRO_MSDU_PG_DRV_CLR			BIT(26)
-+#define MTK_WED_RRO_MSDU_PG_DRV_EN			BIT(31)
-+
-+#define MTK_WED_RRO_MSDU_PG_CTRL0(_n)			(0xe5c + (_n) * 0xc)
-+#define MTK_WED_RRO_MSDU_PG_CTRL1(_n)			(0xe60 + (_n) * 0xc)
-+#define MTK_WED_RRO_MSDU_PG_CTRL2(_n)			(0xe64 + (_n) * 0xc)
-+
-+#define MTK_WED_RRO_RX_D_RX(_n)				(0xe80 + (_n) * 0x10)
-+
-+#define MTK_WED_RRO_RX_MAGIC_CNT			BIT(13)
-+
-+#define MTK_WED_RRO_RX_D_CFG(_n)			(0xea0 + (_n) * 0x4)
-+#define MTK_WED_RRO_RX_D_DRV_CLR			BIT(26)
-+#define MTK_WED_RRO_RX_D_DRV_EN				BIT(31)
-+
-+#define MTK_WED_RRO_PG_BM_RX_DMAM			0xeb0
-+#define MTK_WED_RRO_PG_BM_RX_SDL0			GENMASK(13, 0)
-+
-+#define MTK_WED_RRO_PG_BM_BASE				0xeb4
-+#define MTK_WED_RRO_PG_BM_INIT_PTR			0xeb8
-+#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX			GENMASK(15, 0)
-+#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX		BIT(16)
-+
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX			0xeec
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN		BIT(0)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR		BIT(1)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG	GENMASK(6, 2)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN		BIT(8)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR		BIT(9)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG	GENMASK(14, 10)
-+
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG		0xef4
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN		BIT(0)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR		BIT(1)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG	GENMASK(6, 2)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN		BIT(8)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR		BIT(9)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG	GENMASK(14, 10)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN		BIT(16)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR		BIT(17)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG	GENMASK(22, 18)
-+
-+#define MTK_WED_RX_IND_CMD_CNT0				0xf20
-+#define MTK_WED_RX_IND_CMD_DBG_CNT_EN			BIT(31)
-+
-+#define MTK_WED_RX_IND_CMD_CNT(_n)			(0xf20 + (_n) * 0x4)
-+#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT		GENMASK(15, 0)
-+
-+#define MTK_WED_RX_ADDR_ELEM_CNT(_n)			(0xf48 + (_n) * 0x4)
-+#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT			GENMASK(15, 0)
-+#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT		GENMASK(31, 16)
-+#define MTK_WED_ADDR_ELEM_ACKSN_CNT			GENMASK(27, 0)
-+
-+#define MTK_WED_RX_MSDU_PG_CNT(_n)			(0xf5c + (_n) * 0x4)
-+
-+#define MTK_WED_RX_PN_CHK_CNT 				0xf70
-+#define MTK_WED_PN_CHK_FAIL_CNT				GENMASK(15, 0)
-+
- #define MTK_WED_WOCPU_VIEW_MIOD_BASE		 	0x8000
- #define MTK_WED_PCIE_INT_MASK				0x0
- 
-+#define MTK_WED_PAO_AMSDU_FIFO				0x1800
-+#define MTK_WED_PAO_AMSDU_IS_PRIOR0_RING		BIT(10)
-+
-+#define MTK_WED_PAO_STA_INFO				0x01810
-+#define MTK_WED_PAO_STA_INFO_DO_INIT			BIT(0)
-+#define MTK_WED_PAO_STA_INFO_SET_INIT			BIT(1)
-+
-+#define MTK_WED_PAO_STA_INFO_INIT			0x01814
-+#define MTK_WED_PAO_STA_WTBL_HDRT_MODE			BIT(0)
-+#define MTK_WED_PAO_STA_RMVL				BIT(1)
-+#define MTK_WED_PAO_STA_MAX_AMSDU_LEN			GENMASK(7, 2)
-+#define MTK_WED_PAO_STA_MAX_AMSDU_NUM			GENMASK(11, 8)
-+
-+#define MTK_WED_PAO_HIFTXD_BASE_L(_n)			(0x1980 + (_n) * 0x4)
-+
-+#define MTK_WED_PAO_PSE					0x1910
-+#define MTK_WED_PAO_PSE_RESET				BIT(16)
-+
-+#define MTK_WED_PAO_HIFTXD_CFG				0x1968
-+#define MTK_WED_PAO_HIFTXD_SRC				GENMASK(16, 15)
-+
-+#define MTK_WED_PAO_MON_AMSDU_FIFO_DMAD			0x1a34
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_DMAD(_n)		(0x1a80 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QFPL(_n)		(0x1a84 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QENI(_n)		(0x1a88 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QENO(_n)		(0x1a8c + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_MERG(_n)		(0x1a90 + (_n) * 0x50)
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_CNT8(_n)		(0x1a94 + (_n) * 0x50)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_QGPP_CNT		GENMASK(10, 0)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_PL_CNT		GENMASK(27, 16)
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_CNT9(_n)		(0x1a98 + (_n) * 0x50)
-+#define MTK_WED_PAO_AMSDU_ENG_CUR_ENTRY			GENMASK(10, 0)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_BUF_MERGED		GENMASK(20, 16)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED		GENMASK(28, 24)
-+
-+#define MTK_WED_PAO_MON_QMEM_STS1			0x1e04
-+
-+#define MTK_WED_PAO_MON_QMEM_CNT(_n)			(0x1e0c + (_n) * 0x4)
-+#define MTK_WED_PAO_QMEM_FQ_CNT				GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QCNT			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QCNT			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QCNT			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QCNT			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QCNT			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QCNT			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QCNT			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QCNT			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QCNT			GENMASK(11, 0)
-+
-+#define MTK_WED_PAO_MON_QMEM_PTR(_n)			(0x1e20 + (_n) * 0x4)
-+#define MTK_WED_PAO_QMEM_FQ_HEAD				GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QHEAD			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QHEAD			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QHEAD			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QHEAD			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QHEAD			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QHEAD			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QHEAD			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QHEAD			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QHEAD			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_FQ_TAIL			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QTAIL			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QTAIL			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QTAIL			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QTAIL			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QTAIL			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QTAIL			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QTAIL			GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QTAIL			GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QTAIL			GENMASK(11, 0)
-+
-+#define MTK_WED_PAO_MON_HIFTXD_FETCH_MSDU(_n)		(0x1ec4 + (_n) * 0x4)
-+
-+#define MTK_WED_PCIE_BASE			0x11280000
-+
-+#define MTK_WED_PCIE_BASE0			0x11300000
-+#define MTK_WED_PCIE_BASE1			0x11310000
-+#define MTK_WED_PCIE_BASE2			0x11290000
- #endif
-diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index b2abebe..204051d 100644
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -880,6 +880,13 @@ struct net_device_path {
- 			u8 queue;
- 			u16 wcid;
- 			u8 bss;
-+			u32 usr_info;
-+			u8 tid;
-+			u8 is_fixedrate;
-+			u8 is_prior;
-+			u8 is_sp;
-+			u8 hf;
-+			u8 amsdu_en;
- 		} mtk_wdma;
- 	};
- };
-diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 27cf284..92df4ba 100644
---- a/include/linux/soc/mediatek/mtk_wed.h
-+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -5,11 +5,14 @@
- #include <linux/rcupdate.h>
- #include <linux/regmap.h>
- #include <linux/pci.h>
-+#include <linux/skbuff.h>
-+#include <linux/iopoll.h>
- 
- #define WED_WO_STA_REC			0x6
- 
- #define MTK_WED_TX_QUEUES		2
- #define MTK_WED_RX_QUEUES		2
-+#define MTK_WED_RX_PAGE_QUEUES         3
- 
- enum mtk_wed_wo_cmd {
- 	MTK_WED_WO_CMD_WED_CFG,
-@@ -55,10 +58,13 @@ enum mtk_wed_bus_tye {
- struct mtk_wed_hw;
- struct mtk_wdma_desc;
- 
-+#define MTK_WED_RING_CONFIGURED		BIT(0)
-+
- struct mtk_wed_ring {
- 	struct mtk_wdma_desc *desc;
- 	dma_addr_t desc_phys;
- 	int size;
-+	u32 flags;
- 
- 	u32 reg_base;
- 	void __iomem *wpdma;
-@@ -69,11 +75,18 @@ struct mtk_rxbm_desc {
- 	__le32 token;
- } __packed __aligned(4);
- 
-+struct dma_page_info {
-+	void *addr;
-+	dma_addr_t addr_phys;
-+};
-+
- struct dma_buf {
- 	int size;
--	void **pages;
--	struct mtk_wdma_desc *desc;
-+	int pkt_nums;
-+	void *desc;
-+	int desc_size;
- 	dma_addr_t desc_phys;
-+	struct dma_page_info *pages;
- };
- 
- struct dma_entry {
-@@ -97,6 +110,7 @@ struct mtk_wed_device {
- 	struct device *dev;
- 	struct mtk_wed_hw *hw;
- 	bool init_done, running;
-+	bool wdma_init_done;
- 	int wdma_idx;
- 	int irq;
- 	u8 ver;
-@@ -108,7 +122,11 @@ struct mtk_wed_device {
- 	struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
- 	struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
- 
--	struct dma_buf buf_ring;
-+	struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES];
-+	struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES];
-+	struct mtk_wed_ring ind_cmd_ring;
-+
-+	struct dma_buf tx_buf_ring;
- 
- 	struct {
- 		int size;
-@@ -117,6 +135,8 @@ struct mtk_wed_device {
- 		dma_addr_t desc_phys;
- 	} rx_buf_ring;
- 
-+	struct dma_buf rx_page_buf_ring;
-+
- 	struct {
- 		struct mtk_wed_ring rro_ring;
- 		void __iomem *rro_desc;
-@@ -131,8 +151,9 @@ struct mtk_wed_device {
- 			struct platform_device *platform_dev;
- 			struct pci_dev *pci_dev;
- 		};
-+		enum mtk_wed_bus_tye bus_type;
- 		void __iomem *base;
--		u32 bus_type;
-+		void __iomem *regs;
- 		u32 phy_base;
- 
- 		u32 wpdma_phys;
-@@ -141,10 +162,14 @@ struct mtk_wed_device {
- 		u32 wpdma_tx;
- 		u32 wpdma_txfree;
- 		u32 wpdma_rx_glo;
--		u32 wpdma_rx;
-+		u32 wpdma_rx[MTK_WED_RX_QUEUES];
-+		u32 wpdma_rx_rro[MTK_WED_RX_QUEUES];
-+		u32 wpdma_rx_pg;
- 
- 		u8 tx_tbit[MTK_WED_TX_QUEUES];
- 		u8 rx_tbit[MTK_WED_RX_QUEUES];
-+		u8 rro_rx_tbit[MTK_WED_RX_QUEUES];
-+		u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES];
- 		u8 txfree_tbit;
- 
- 		u16 token_start;
-@@ -154,12 +179,26 @@ struct mtk_wed_device {
- 		unsigned int rx_size;
- 
- 		bool wcid_512;
--
-+		bool hwrro;
-+		bool msi;
-+
-+		u8 max_amsdu_nums;
-+		u32 max_amsdu_len;
-+
-+		struct {
-+			u8 se_group_nums;
-+			u16 win_size;
-+			u16 particular_sid;
-+			u32 ack_sn_addr;
-+			dma_addr_t particular_se_phys;
-+			dma_addr_t addr_elem_phys[1024];
-+		} ind_cmd;
-+
-+		u32 chip_id;
- 		u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
- 		int (*offload_enable)(struct mtk_wed_device *wed);
- 		void (*offload_disable)(struct mtk_wed_device *wed);
--		u32 (*init_rx_buf)(struct mtk_wed_device *wed,
--				   int pkt_num);
-+		u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size);
- 		void (*release_rx_buf)(struct mtk_wed_device *wed);
- 		void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
- 					   struct mtk_wed_wo_rx_stats *stats);
-@@ -180,6 +219,11 @@ struct mtk_wed_ops {
- 				 void __iomem *regs);
- 	int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
- 			     void __iomem *regs, bool reset);
-+	int (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+			     void __iomem *regs);
-+	int (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+			     void __iomem *regs);
-+	int (*ind_rx_ring_setup)(struct mtk_wed_device *dev, void __iomem *regs);
- 	int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- 			  void *data, int len);
- 	void (*detach)(struct mtk_wed_device *dev);
-@@ -196,6 +240,7 @@ struct mtk_wed_ops {
- 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
- 	void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
- 			  u32 reason, u32 hash);
-+	void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask);
- };
- 
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -224,12 +269,21 @@ static inline bool
- mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- {
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+	if (dev->ver == 3 && !dev->wlan.hwrro)
-+		return false;
-+
- 	return dev->ver != 1;
- #else
- 	return false;
- #endif
- }
- 
-+static inline bool
-+mtk_wed_device_support_pao(struct mtk_wed_device *dev)
-+{
-+	return dev->ver == 3;
-+}
-+
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- #define mtk_wed_device_active(_dev) !!(_dev)->ops
- #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
-@@ -243,6 +297,12 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- 	(_dev)->ops->txfree_ring_setup(_dev, _regs)
- #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
- 	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset)
-+#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
-+	(_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
-+	(_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \
-+	(_dev)->ops->ind_rx_ring_setup(_dev, _regs)
- #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
- 	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
- #define mtk_wed_device_reg_read(_dev, _reg) \
-@@ -257,6 +317,9 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- 	(_dev)->ops->reset_dma(_dev)
- #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
- 	(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
-+#define mtk_wed_device_start_hwrro(_dev, _mask) \
-+	(_dev)->ops->start_hwrro(_dev, _mask)
-+
- #else
- static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- {
-@@ -268,6 +331,9 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
- #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
- #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
-+#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs)  -ENODEV
-+#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs)  -ENODEV
- #define mtk_wed_device_reg_read(_dev, _reg) 0
- #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
- #define mtk_wed_device_irq_get(_dev, _mask) 0
-@@ -275,6 +341,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_dma_reset(_dev) do {} while (0)
- #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
- #define mtk_wed_device_ppe_check(_dev, _hash)  do {} while (0)
-+#define mtk_wed_device_start_hwrro(_dev, _mask) do {} while (0)
- #endif
- 
- #endif
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch
deleted file mode 100644
index 328a4bc..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch
+++ /dev/null
@@ -1,642 +0,0 @@
-From f0b9f017b170690be346d3e08371fdadca0d59d3 Mon Sep 17 00:00:00 2001
-From: mtk27745 <rex.lu@mediatek.com>
-Date: Mon, 18 Sep 2023 13:22:44 +0800
-Subject: [PATCH] mtk wed add wed3 ser support
-
----
- drivers/net/ethernet/mediatek/mtk_wed.c      | 260 +++++++++++++++++--
- drivers/net/ethernet/mediatek/mtk_wed_regs.h |  73 +++++-
- include/linux/soc/mediatek/mtk_wed.h         |   6 +-
- 3 files changed, 310 insertions(+), 29 deletions(-)
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 561fc6c..f20a4ae 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -99,16 +99,70 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- 	u32 status;
- 	u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
- 	int busy, i;
-+	u32 value;
- 
- 	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
- 	busy = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
--			       !(status & mask), 0, 10000);
-+				  !(status & mask), 0, 10000);
- 
-+	if (dev->hw->version == 3) {
-+		wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+		wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_PREF_TX_CFG);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_PREF_RX_CFG);
-+
-+		wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+		wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_WRBK_TX_CFG);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_WRBK_RX_CFG);
-+
-+		/* Prefetch FIFO */
-+		wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
-+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
-+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
-+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
-+			 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
-+
-+		/* Core FIFO */
-+		value = (MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
-+
-+		wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
-+		wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
-+
-+		/* Writeback FIFO */
-+		wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+		wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+
-+		wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+
-+		/* Prefetch ring status */
-+		wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
-+		/* Writeback ring status */
-+		wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
-+	}
- 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
- 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
- 
--	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
--		if (!dev->rx_wdma[i].desc) {
-+	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+		if (!dev->tx_wdma[i].desc) {
- 			wdma_w32(dev, MTK_WDMA_RING_RX(i) +
- 				 MTK_WED_RING_OFS_CPU_IDX, 0);
- 	}
-@@ -121,16 +175,65 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
- {
- 	u32 status;
- 	u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
--	int i;
-+	int busy, i;
-+	u32 value;
- 
- 	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
- 	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
- 			       !(status & mask), 0, 10000))
- 		WARN_ON_ONCE(1);
- 
-+	if (dev->hw->version == 3) {
-+		wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+		wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_PREF_TX_CFG);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_PREF_RX_CFG);
-+
-+		wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+		wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_WRBK_TX_CFG);
-+		busy = read_poll_timeout(wdma_r32, status,
-+					 !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
-+					 false, dev, MTK_WDMA_WRBK_RX_CFG);
-+
-+		/* Prefetch FIFO */
-+		wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
-+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
-+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
-+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
-+			 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
-+		/* Core FIFO */
-+		value = (MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
-+			 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
-+
-+		wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
-+		wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
-+		/* Writeback FIFO */
-+		wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+		wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+
-+		wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+
-+		/* Prefetch ring status */
-+		wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
-+		/* Writeback ring status */
-+		wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
-+		wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
-+	}
- 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
- 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
--	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
- 		wdma_w32(dev, MTK_WDMA_RING_TX(i) +
- 			 MTK_WED_RING_OFS_CPU_IDX, 0);
- }
-@@ -913,7 +1016,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- 				MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
- 
- 			wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
--			//wdma_w32(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+			wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
- 			if (mtk_wed_get_rx_capa(dev)) {
- 				wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
- 					MTK_WED_WPDMA_RX_D_PREF_EN |
-@@ -1476,13 +1579,30 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
- 			     &state, sizeof(state), true);
- 
-+	if (dev->wlan.hwrro) {
-+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
-+		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS,
-+				  MTK_WED_RX_IND_CMD_BUSY);
-+		mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG);
-+	}
- 	wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
- 	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
- 				 MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
-+	if (dev->hw->version == 3)
-+		busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+					 MTK_WED_WPDMA_RX_D_PREF_BUSY);
- 	if (busy) {
- 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
- 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
- 	} else {
-+		if (dev->hw->version == 3) {
-+			/*1.a. Disable Prefetch HW*/
-+			wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, MTK_WED_WPDMA_RX_D_PREF_EN);
-+			mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+					  MTK_WED_WPDMA_RX_D_PREF_BUSY);
-+			wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
-+				MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL);
-+		}
- 		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
- 			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
- 			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
-@@ -1510,6 +1630,24 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 		wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
- 	}
- 
-+	if (dev->wlan.hwrro) {
-+		/* Disable RRO MSDU Page Drv */
-+		wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+
-+		/* Disable RRO Data Drv */
-+		wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
-+
-+		/* RRO MSDU Page Drv Reset */
-+		wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+		mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
-+				  MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+
-+		/* RRO Data Drv Reset */
-+		wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_CLR);
-+		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2),
-+				  MTK_WED_RRO_RX_D_DRV_CLR);
-+	}
-+
- 	/* reset route qm */
- 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
- 	busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-@@ -1517,8 +1655,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 	if (busy) {
- 		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
- 	} else {
--		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
--			MTK_WED_RTQM_Q_RST);
-+		if (dev->hw->version == 3) {
-+			wed_set(dev, MTK_WED_RTQM_RST, BIT(0));
-+			wed_clr(dev, MTK_WED_RTQM_RST, BIT(0));
-+			mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
-+		} else
-+			wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-+				MTK_WED_RTQM_Q_RST);
- 	}
- 
- 	/* reset tx wdma */
-@@ -1526,8 +1669,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 
- 	/* reset tx wdma drv */
- 	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
--	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
--			  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
-+	if (dev->hw->version == 3)
-+		mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS,
-+				  MTK_WED_WPDMA_STATUS_TX_DRV);
-+	else
-+		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+				  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
-+
- 	mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
- 
- 	/* reset wed rx dma */
-@@ -1545,9 +1693,17 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 	/* reset rx bm */
- 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
- 	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
--			   MTK_WED_CTRL_WED_RX_BM_BUSY);
-+			  MTK_WED_CTRL_WED_RX_BM_BUSY);
- 	mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
- 
-+	if (dev->wlan.hwrro) {
-+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
-+		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+				  MTK_WED_CTRL_WED_RX_PG_BM_BUSY);
-+		wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
-+		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
-+	}
-+
- 	/* wo change to enable state */
- 	state = WO_STATE_ENABLE;
- 	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-@@ -1564,6 +1720,9 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- 	}
- 
- 	mtk_wed_free_rx_buffer(dev);
-+
-+	if (dev->wlan.hwrro)
-+		mtk_wed_rx_page_free_buffer(dev);
- }
- 
- 
-@@ -1597,18 +1756,54 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 
- 	/* 2. Reset WDMA Rx DMA/Driver_Engine */
- 	busy = !!mtk_wdma_rx_reset(dev);
-+	if (dev->hw->version == 3) {
-+		val = wed_r32(dev, MTK_WED_WDMA_GLO_CFG);
-+		val |= MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-+		val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN;
-+		wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val);
-+	} else
-+		wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
- 
--	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
- 	busy = !!(busy ||
- 		  mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
--					 MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
-+				    MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
-+	if (dev->hw->version == 3)
-+		busy = !!(busy ||
-+			  mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+					    MTK_WED_WDMA_RX_PREF_BUSY));
- 
- 	if (busy) {
- 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
- 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
- 	} else {
-+		if (dev->hw->version == 3) {
-+			/*1.a. Disable Prefetch HW*/
-+			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
-+			mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+					  MTK_WED_WDMA_RX_PREF_BUSY);
-+			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_DDONE2_EN);
-+
-+			/* reset prefetch index */
-+			wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+				MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+				MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+				MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+				MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+			/* reset prefetch FIFO */
-+			wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
-+				MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
-+				MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
-+			wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
-+			/*2. Reset dma index*/
-+			wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
-+				MTK_WED_WDMA_RESET_IDX_RX_ALL);
-+		}
- 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
--			MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV);
-+			MTK_WED_WDMA_RESET_IDX_RX |
-+			MTK_WED_WDMA_RESET_IDX_DRV);
- 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
- 
- 		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-@@ -1623,9 +1818,15 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
- 
- 	for (i = 0; i < 100; i++) {
--		val = wed_r32(dev, MTK_WED_TX_BM_INTF);
--		if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
--			break;
-+		if (dev->ver > MTK_WED_V1) {
-+			val = wed_r32(dev, MTK_WED_TX_TKID_INTF);
-+			if (FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP, val) == 0x40)
-+				break;
-+		} else {
-+			val = wed_r32(dev, MTK_WED_TX_BM_INTF);
-+			if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
-+				break;
-+		}
- 	}
- 	mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
- 
-@@ -1634,18 +1835,20 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 
- 	/* 4. Reset WED WPDMA Tx Driver Engine */
- 	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
--				      MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
-+				 MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
- 	wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- 		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
- 		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
- 
- 	busy = !!(busy ||
- 		  mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
--					 MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
-+				    MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
- 	if (busy) {
- 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
- 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
- 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV);
-+		if (dev->hw->version == 3)
-+			wed_w32(dev, MTK_WED_RX1_CTRL2, 0);
- 	} else {
- 		wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
- 			MTK_WED_WPDMA_RESET_IDX_TX |
-@@ -1658,11 +1861,17 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 		}
- 	}
- 
--	if (dev->ver > MTK_WED_V1) {
--		dev->init_done = false;
--		mtk_wed_rx_reset(dev);
-+	dev->init_done = false;
-+
-+	if (dev->hw->version == 3) {
-+		/*reset wed pao*/
-+		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+		mtk_wed_reset(dev, MTK_WED_RESET_TX_PAO);
- 	}
- 
-+	if (mtk_wed_get_rx_capa(dev))
-+		mtk_wed_rx_reset(dev);
-+
- }
- 
- static int
-@@ -1875,7 +2084,7 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
- }
- 
- static void
--mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
-+mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask, bool reset)
- {
- 	int idx, ret;
- 
-@@ -1885,6 +2094,11 @@ mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
- 	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
- 		return;
- 
-+	if (reset) {
-+		wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+		return;
-+	}
-+	
- 	wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
- 	wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 25be547..4379dc4 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -42,6 +42,8 @@ struct mtk_wdma_desc {
- #define MTK_WED_RESET					0x008
- #define MTK_WED_RESET_TX_BM				BIT(0)
- #define MTK_WED_RESET_RX_BM				BIT(1)
-+#define MTK_WED_RESET_RX_PG_BM				BIT(2)
-+#define MTK_WED_RESET_RRO_RX_TO_PG			BIT(3)
- #define MTK_WED_RESET_TX_FREE_AGENT			BIT(4)
- #define MTK_WED_RESET_WPDMA_TX_DRV			BIT(8)
- #define MTK_WED_RESET_WPDMA_RX_DRV			BIT(9)
-@@ -64,7 +66,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY		BIT(3)
- #define MTK_WED_CTRL_WED_RX_IND_CMD_EN			BIT(5)
- #define MTK_WED_CTRL_WED_RX_PG_BM_EN			BIT(6)
--#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU			BIT(7)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY			BIT(7)
- #define MTK_WED_CTRL_WED_TX_BM_EN			BIT(8)
- #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
- #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
-@@ -123,6 +125,10 @@ struct mtk_wdma_desc {
- #define MTK_WED_STATUS					0x060
- #define MTK_WED_STATUS_TX				GENMASK(15, 8)
- 
-+#define MTK_WED_WPDMA_STATUS				0x068
-+#define MTK_WED_WPDMA_STATUS_TX_DRV			GENMASK(15, 8)
-+
-+
- #define MTK_WED_TX_BM_CTRL				0x080
- #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM			GENMASK(6, 0)
- #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM			GENMASK(22, 16)
-@@ -167,6 +173,9 @@ struct mtk_wdma_desc {
- 
- #define MTK_WED_TX_TKID_CTRL_PAUSE			BIT(28)
- 
-+#define MTK_WED_TX_TKID_INTF				0x0dc
-+#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP		GENMASK(25, 16)
-+
- #define MTK_WED_TX_TKID_DYN_THR				0x0e0
- #define MTK_WED_TX_TKID_DYN_THR_LO			GENMASK(6, 0)
- #define MTK_WED_TX_TKID_DYN_THR_HI			GENMASK(22, 16)
-@@ -203,10 +212,11 @@ struct mtk_wdma_desc {
- #define MTK_WED_GLO_CFG_RX_2B_OFFSET			BIT(31)
- 
- #define MTK_WED_RESET_IDX				0x20c
--#define MTK_WED_RESET_IDX_TX				GENMASK(3, 0)
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WED_RESET_IDX_TX				GENMASK(1, 0)
- #define MTK_WED_RESET_IDX_RX				GENMASK(7, 6)
- #else
-+#define MTK_WED_RESET_IDX_TX				GENMASK(3, 0)
- #define MTK_WED_RESET_IDX_RX				GENMASK(17, 16)
- #endif
- #define MTK_WED_RESET_WPDMA_IDX_RX			GENMASK(31, 30)
-@@ -221,6 +231,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_RING_RX_DATA(_n)			(0x420 + (_n) * 0x10)
- 
- #define MTK_WED_SCR0					0x3c0
-+#define MTK_WED_RX1_CTRL2				0x418
- #define MTK_WED_WPDMA_INT_TRIGGER			0x504
- #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE		BIT(1)
- #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE		GENMASK(5, 4)
-@@ -336,6 +347,7 @@ struct mtk_wdma_desc {
- 
- #define MTK_WED_WPDMA_RX_D_RST_IDX			0x760
- #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX			GENMASK(17, 16)
-+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL		BIT(20)
- #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX			GENMASK(25, 24)
- 
- #define MTK_WED_WPDMA_RX_GLO_CFG			0x76c
-@@ -352,6 +364,7 @@ struct mtk_wdma_desc {
- 
- #define MTK_WED_WPDMA_RX_D_PREF_CFG			0x7b4
- #define MTK_WED_WPDMA_RX_D_PREF_EN			BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_BUSY		BIT(1)
- #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE		GENMASK(12, 8)
- #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES		GENMASK(21, 16)
- 
-@@ -373,11 +386,13 @@ struct mtk_wdma_desc {
- 
- #define MTK_WED_WDMA_RX_PREF_CFG			0x950
- #define MTK_WED_WDMA_RX_PREF_EN				BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_BUSY			BIT(1)
- #define MTK_WED_WDMA_RX_PREF_BURST_SIZE			GENMASK(12, 8)
- #define MTK_WED_WDMA_RX_PREF_LOW_THRES			GENMASK(21, 16)
- #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR		BIT(24)
- #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR		BIT(25)
- #define MTK_WED_WDMA_RX_PREF_DDONE2_EN			BIT(26)
-+#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY		BIT(27)
- 
- #define MTK_WED_WDMA_RX_PREF_FIFO_CFG			0x95C
- #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR		BIT(0)
-@@ -406,6 +421,7 @@ struct mtk_wdma_desc {
- 
- #define MTK_WED_WDMA_RESET_IDX				0xa08
- #define MTK_WED_WDMA_RESET_IDX_RX			GENMASK(17, 16)
-+#define MTK_WED_WDMA_RESET_IDX_RX_ALL			BIT(20)
- #define MTK_WED_WDMA_RESET_IDX_DRV			GENMASK(25, 24)
- 
- #define MTK_WED_WDMA_INT_CLR				0xa24
-@@ -474,21 +490,66 @@ struct mtk_wdma_desc {
- #define MTK_WDMA_INT_MASK_RX_DELAY			BIT(30)
- #define MTK_WDMA_INT_MASK_RX_COHERENT			BIT(31)
- 
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG			0x238
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR		BIT(0)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR		BIT(4)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR		BIT(8)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR		BIT(12)
-+
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG			0x23c
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR		BIT(0)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR		BIT(4)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR		BIT(8)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR		BIT(12)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR		BIT(15)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR		BIT(18)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR		BIT(21)
-+
-+
-+
- #define MTK_WDMA_INT_GRP1				0x250
- #define MTK_WDMA_INT_GRP2				0x254
- 
- #define MTK_WDMA_PREF_TX_CFG				0x2d0
- #define MTK_WDMA_PREF_TX_CFG_PREF_EN			BIT(0)
-+#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY			BIT(1)
- 
- #define MTK_WDMA_PREF_RX_CFG				0x2dc
- #define MTK_WDMA_PREF_RX_CFG_PREF_EN			BIT(0)
-+#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY			BIT(1)
-+
-+#define MTK_WDMA_PREF_RX_FIFO_CFG			0x2e0
-+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR		BIT(0)
-+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR		BIT(16)
-+
-+#define MTK_WDMA_PREF_TX_FIFO_CFG			0x2d4
-+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR		BIT(0)
-+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR		BIT(16)
-+
-+#define MTK_WDMA_PREF_SIDX_CFG				0x2e4
-+#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
-+#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
- 
- #define MTK_WDMA_WRBK_TX_CFG				0x300
-+#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY			BIT(0)
- #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN			BIT(30)
- 
-+#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n)			(0x304 + (_n) * 0x4)
-+#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR		BIT(0)
-+
-+
- #define MTK_WDMA_WRBK_RX_CFG				0x344
-+#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY			BIT(0)
- #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN			BIT(30)
- 
-+#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n)			(0x348 + (_n) * 0x4)
-+#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR		BIT(0)
-+
-+
-+#define MTK_WDMA_WRBK_SIDX_CFG				0x388
-+#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
-+#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
-+
- #define MTK_PCIE_MIRROR_MAP(n)				((n) ? 0x4 : 0x0)
- #define MTK_PCIE_MIRROR_MAP_EN				BIT(0)
- #define MTK_PCIE_MIRROR_MAP_WED_ID			BIT(1)
-@@ -502,6 +563,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q_DBG_BYPASS			BIT(5)
- #define MTK_WED_RTQM_TXDMAD_FPORT			GENMASK(23, 20)
- 
-+#define MTK_WED_RTQM_RST				0xb04
-+
-+
- #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT		0xb1c
- #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n)		(0xb20 + (_n) * 0x4)
- #define	MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT			0xb28
-@@ -691,6 +755,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR		BIT(17)
- #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG	GENMASK(22, 18)
- 
-+#define MTK_WED_RRO_RX_HW_STS				0xf00
-+#define MTK_WED_RX_IND_CMD_BUSY			GENMASK(31, 0)
-+
- #define MTK_WED_RX_IND_CMD_CNT0				0xf20
- #define MTK_WED_RX_IND_CMD_DBG_CNT_EN			BIT(31)
- 
-diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 92df4ba..1438692 100644
---- a/include/linux/soc/mediatek/mtk_wed.h
-+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -240,7 +240,7 @@ struct mtk_wed_ops {
- 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
- 	void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
- 			  u32 reason, u32 hash);
--	void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask);
-+	void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask, bool reset);
- };
- 
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -317,8 +317,8 @@ mtk_wed_device_support_pao(struct mtk_wed_device *dev)
- 	(_dev)->ops->reset_dma(_dev)
- #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
- 	(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
--#define mtk_wed_device_start_hwrro(_dev, _mask) \
--	(_dev)->ops->start_hwrro(_dev, _mask)
-+#define mtk_wed_device_start_hwrro(_dev, _mask, _reset) \
-+	(_dev)->ops->start_hwrro(_dev, _mask, _reset)
- 
- #else
- static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
--- 
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
similarity index 100%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
rename to autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
index 1ba25be..4a9bfae 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
@@ -1,14 +1,14 @@
-From b80c745d2b90b30558e4f5b12060af956ae8e76d Mon Sep 17 00:00:00 2001
+From 35623475d9eb8522756b0b4833c95a31a0ceb10b Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Mon, 18 Sep 2023 10:52:27 +0800
-Subject: [PATCH 02/22] mt7622 backport nf hw offload framework and upstream
+Subject: [PATCH 01/24] mt7622 backport nf hw offload framework and upstream
  hnat plus xt-FLOWOFFLOAD update v2
 
 ---
  drivers/net/ethernet/mediatek/Makefile        |    3 +-
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   |   25 +-
  drivers/net/ethernet/mediatek/mtk_eth_soc.h   |   19 +-
- drivers/net/ethernet/mediatek/mtk_ppe.c       |  510 +++++++
+ drivers/net/ethernet/mediatek/mtk_ppe.c       |  514 +++++++
  drivers/net/ethernet/mediatek/mtk_ppe.h       |  288 ++++
  .../net/ethernet/mediatek/mtk_ppe_debugfs.c   |  214 +++
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |  535 ++++++++
@@ -46,7 +46,7 @@
  net/netfilter/nf_flow_table_ip.c              |  447 +++---
  net/netfilter/nf_flow_table_offload.c         | 1199 +++++++++++++++++
  net/netfilter/xt_FLOWOFFLOAD.c                |  800 +++++++++++
- 41 files changed, 4995 insertions(+), 435 deletions(-)
+ 41 files changed, 4999 insertions(+), 435 deletions(-)
  mode change 100644 => 100755 drivers/net/ethernet/mediatek/Makefile
  mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.c
  mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -76,10 +76,10 @@
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 old mode 100644
 new mode 100755
-index c4bea4d..9c85e16
+index 37fd338..20b2943
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -3573,6 +3573,7 @@ static int mtk_open(struct net_device *dev)
+@@ -4001,6 +4001,7 @@ static int mtk_open(struct net_device *dev)
  	u32 id = mtk_mac2xgmii_id(eth, mac->id);
  	int err, i;
  	struct device_node *phy_node;
@@ -87,7 +87,7 @@
  
  	err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
  	if (err) {
-@@ -3650,7 +3651,10 @@ static int mtk_open(struct net_device *dev)
+@@ -4085,7 +4086,10 @@ static int mtk_open(struct net_device *dev)
  		regmap_write(eth->sgmii->pcs[id].regmap,
  			     SGMSYS_QPHY_PWR_STATE_CTRL, 0);
  
@@ -99,7 +99,7 @@
  
  	return 0;
  }
-@@ -3730,6 +3734,9 @@ static int mtk_stop(struct net_device *dev)
+@@ -4172,6 +4176,9 @@ static int mtk_stop(struct net_device *dev)
  
  	mtk_dma_free(eth);
  
@@ -109,7 +109,7 @@
  	return 0;
  }
  
-@@ -4576,6 +4583,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+@@ -5081,6 +5088,7 @@ static const struct net_device_ops mtk_netdev_ops = {
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller	= mtk_poll_controller,
  #endif
@@ -117,7 +117,7 @@
  };
  
  static void mux_poll(struct work_struct *work)
-@@ -5161,6 +5169,17 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5711,6 +5719,17 @@ static int mtk_probe(struct platform_device *pdev)
  			goto err_free_dev;
  	}
  
@@ -135,7 +135,7 @@
  	for (i = 0; i < MTK_MAX_DEVS; i++) {
  		if (!eth->netdev[i])
  			continue;
-@@ -5254,6 +5273,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5811,6 +5830,7 @@ static const struct mtk_soc_data mt2701_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -143,7 +143,7 @@
  	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5271,6 +5291,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5828,6 +5848,7 @@ static const struct mtk_soc_data mt7621_data = {
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -151,7 +151,7 @@
  	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5289,6 +5310,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5846,6 +5867,7 @@ static const struct mtk_soc_data mt7622_data = {
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -159,7 +159,7 @@
  	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5306,6 +5328,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5863,6 +5885,7 @@ static const struct mtk_soc_data mt7623_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -170,7 +170,7 @@
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 old mode 100644
 new mode 100755
-index 8a9b615..a87e46d
+index 26a99d1..4d3a63c
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 @@ -15,6 +15,8 @@
@@ -182,7 +182,7 @@
  
  #define MTK_QDMA_PAGE_SIZE	2048
  #define	MTK_MAX_RX_LENGTH	1536
-@@ -44,7 +46,8 @@
+@@ -47,7 +49,8 @@
  				 NETIF_F_HW_VLAN_CTAG_TX | \
  				 NETIF_F_SG | NETIF_F_TSO | \
  				 NETIF_F_TSO6 | \
@@ -192,7 +192,7 @@
  #define MTK_SET_FEATURES	(NETIF_F_LRO | \
  				 NETIF_F_HW_VLAN_CTAG_RX)
  #define MTK_HW_FEATURES_MT7628	(NETIF_F_SG | NETIF_F_RXCSUM)
-@@ -127,6 +130,7 @@
+@@ -134,6 +137,7 @@
  #define MTK_GDMA_UCS_EN		BIT(20)
  #define MTK_GDMA_STRP_CRC	BIT(16)
  #define MTK_GDMA_TO_PDMA	0x0
@@ -200,7 +200,7 @@
  #define MTK_GDMA_DROP_ALL	0x7777
  
  /* GDM Egress Control Register */
-@@ -617,6 +621,12 @@
+@@ -661,6 +665,12 @@
  #define RX_DMA_TCI(_x)		((_x) & (VLAN_PRIO_MASK | VLAN_VID_MASK))
  #define RX_DMA_VPID(_x)		(((_x) >> 16) & 0xffff)
  
@@ -213,7 +213,7 @@
  /* QDMA descriptor rxd4 */
  #define RX_DMA_L4_VALID		BIT(24)
  #define RX_DMA_L4_VALID_PDMA	BIT(30)		/* when PDMA is used */
-@@ -1651,6 +1661,7 @@ struct mtk_soc_data {
+@@ -1712,6 +1722,7 @@ struct mtk_soc_data {
  	u64		caps;
  	u64		required_clks;
  	bool		required_pctl;
@@ -221,7 +221,7 @@
  	netdev_features_t hw_features;
  	bool		has_sram;
  	struct {
-@@ -1847,6 +1858,9 @@ struct mtk_eth {
+@@ -1912,6 +1923,9 @@ struct mtk_eth {
  	int				ip_align;
  	spinlock_t			syscfg0_lock;
  	struct timer_list		mtk_dma_monitor_timer;
@@ -231,7 +231,7 @@
  };
  
  /* struct mtk_mac -	the structure that holds the info about the MACs of the
-@@ -1927,6 +1941,9 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+@@ -1993,6 +2007,9 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
  int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
  void mtk_usxgmii_link_poll(struct work_struct *work);
  
@@ -243,7 +243,7 @@
  #endif /* MTK_ETH_H */
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
 new file mode 100644
-index 0000000..27b5be5
+index 0000000..6965d98
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -0,0 +1,514 @@
@@ -1967,10 +1967,10 @@
 +
 +#endif
 diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
-index 078c0f4..f8a98d8 100644
+index 555ba50..25dcff2 100644
 --- a/drivers/net/ppp/ppp_generic.c
 +++ b/drivers/net/ppp/ppp_generic.c
-@@ -1378,12 +1378,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
+@@ -1380,12 +1380,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
  		ppp_destroy_interface(ppp);
  }
  
@@ -2043,10 +2043,10 @@
  
  static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index 631d158..ef44d9a 100644
+index 1c1ab37..44842a2 100644
 --- a/include/linux/netdevice.h
 +++ b/include/linux/netdevice.h
-@@ -838,6 +838,59 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+@@ -843,6 +843,59 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  				       struct sk_buff *skb,
  				       struct net_device *sb_dev);
  
@@ -2106,7 +2106,7 @@
  enum tc_setup_type {
  	TC_SETUP_QDISC_MQPRIO,
  	TC_SETUP_CLSU32,
-@@ -853,6 +906,7 @@ enum tc_setup_type {
+@@ -858,6 +911,7 @@ enum tc_setup_type {
  	TC_SETUP_ROOT_QDISC,
  	TC_SETUP_QDISC_GRED,
  	TC_SETUP_QDISC_TAPRIO,
@@ -2114,7 +2114,7 @@
  };
  
  /* These structures hold the attributes of bpf state that are being passed
-@@ -1248,6 +1302,8 @@ struct tlsdev_ops;
+@@ -1253,6 +1307,8 @@ struct tlsdev_ops;
   *	Get devlink port instance associated with a given netdev.
   *	Called with a reference on the netdevice and devlink locks only,
   *	rtnl_lock is not held.
@@ -2123,7 +2123,7 @@
   */
  struct net_device_ops {
  	int			(*ndo_init)(struct net_device *dev);
-@@ -1445,6 +1501,8 @@ struct net_device_ops {
+@@ -1450,6 +1506,8 @@ struct net_device_ops {
  	int			(*ndo_xsk_wakeup)(struct net_device *dev,
  						  u32 queue_id, u32 flags);
  	struct devlink_port *	(*ndo_get_devlink_port)(struct net_device *dev);
@@ -2132,7 +2132,7 @@
  };
  
  /**
-@@ -2670,6 +2728,8 @@ void dev_remove_offload(struct packet_offload *po);
+@@ -2689,6 +2747,8 @@ void dev_remove_offload(struct packet_offload *po);
  
  int dev_get_iflink(const struct net_device *dev);
  int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
@@ -2210,7 +2210,7 @@
 -
  #endif /* _NF_CONNTRACK_IPV6_H*/
 diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
-index 90690e3..ce0bc3e 100644
+index 90690e3..38a8d3f 100644
 --- a/include/net/netfilter/nf_conntrack.h
 +++ b/include/net/netfilter/nf_conntrack.h
 @@ -105,6 +105,8 @@ struct nf_conn {
@@ -2222,7 +2222,7 @@
  };
  
  static inline struct nf_conn *
-@@ -279,6 +279,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
+@@ -279,6 +281,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
  	       !nf_ct_is_dying(ct);
  }
  
@@ -2264,7 +2264,7 @@
  
  int nf_conntrack_acct_init(void);
 diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index 68d7fc9..feac793 100644
+index 68d7fc9..7374cb2 100644
 --- a/include/net/netfilter/nf_flow_table.h
 +++ b/include/net/netfilter/nf_flow_table.h
 @@ -8,31 +8,101 @@
@@ -2370,7 +2370,7 @@
  
  struct flow_offload_tuple {
  	union {
-@@ -52,13 +120,30 @@ struct flow_offload_tuple {
+@@ -52,13 +122,30 @@ struct flow_offload_tuple {
  
  	u8				l3proto;
  	u8				l4proto;
@@ -2406,7 +2406,7 @@
  	};
  };
  
-@@ -67,52 +152,140 @@ struct flow_offload_tuple_rhash {
+@@ -67,52 +154,140 @@ struct flow_offload_tuple_rhash {
  	struct flow_offload_tuple	tuple;
  };
  
@@ -2569,7 +2569,7 @@
  
  struct flow_ports {
  	__be16 source, dest;
-@@ -126,4 +299,41 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+@@ -126,4 +301,41 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
  #define MODULE_ALIAS_NF_FLOWTABLE(family)	\
  	MODULE_ALIAS("nf-flowtable-" __stringify(family))
  
@@ -2685,10 +2685,10 @@
 +
 +#endif /* _XT_FLOWOFFLOAD_H */
 diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
-index 0a3a167..6112266 100644
+index dd7e09e..c373f1d 100644
 --- a/net/8021q/vlan_dev.c
 +++ b/net/8021q/vlan_dev.c
-@@ -747,6 +747,26 @@ static int vlan_dev_get_iflink(const struct net_device *dev)
+@@ -771,6 +771,26 @@ static int vlan_dev_get_iflink(const struct net_device *dev)
  	return real_dev->ifindex;
  }
  
@@ -2715,7 +2715,7 @@
  static const struct ethtool_ops vlan_ethtool_ops = {
  	.get_link_ksettings	= vlan_ethtool_get_link_ksettings,
  	.get_drvinfo	        = vlan_ethtool_get_drvinfo,
-@@ -785,6 +805,7 @@ static const struct net_device_ops vlan_netdev_ops = {
+@@ -809,6 +829,7 @@ static const struct net_device_ops vlan_netdev_ops = {
  #endif
  	.ndo_fix_features	= vlan_dev_fix_features,
  	.ndo_get_iflink		= vlan_dev_get_iflink,
@@ -2724,10 +2724,10 @@
  
  static void vlan_dev_free(struct net_device *dev)
 diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
-index 501f77f..0940b44 100644
+index ab201d5..deec45b 100644
 --- a/net/bridge/br_device.c
 +++ b/net/bridge/br_device.c
-@@ -377,6 +377,54 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
+@@ -385,6 +385,54 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
  	return br_del_if(br, slave_dev);
  }
  
@@ -2782,7 +2782,7 @@
  static const struct ethtool_ops br_ethtool_ops = {
  	.get_drvinfo    = br_getinfo,
  	.get_link	= ethtool_op_get_link,
-@@ -410,6 +458,7 @@ static const struct net_device_ops br_netdev_ops = {
+@@ -418,6 +466,7 @@ static const struct net_device_ops br_netdev_ops = {
  	.ndo_bridge_setlink	 = br_setlink,
  	.ndo_bridge_dellink	 = br_dellink,
  	.ndo_features_check	 = passthru_features_check,
@@ -2895,10 +2895,10 @@
  		     struct bridge_vlan_info *p_vinfo)
  {
 diff --git a/net/core/dev.c b/net/core/dev.c
-index 54cc544..a117bd0 100644
+index ef7362b..5bade26 100644
 --- a/net/core/dev.c
 +++ b/net/core/dev.c
-@@ -639,6 +639,52 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+@@ -722,6 +722,52 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
  }
  EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
  
@@ -2952,7 +2952,7 @@
   *	__dev_get_by_name	- find a device by its name
   *	@net: the applicable net namespace
 diff --git a/net/dsa/slave.c b/net/dsa/slave.c
-index e2b91b3..2dfaa1e 100644
+index cd5b354..2ea9ec1 100644
 --- a/net/dsa/slave.c
 +++ b/net/dsa/slave.c
 @@ -1031,14 +1031,32 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
@@ -3042,7 +3042,7 @@
  	tristate "Netfilter IPv4 packet duplication to alternate destination"
  	depends on !NF_CONNTRACK || NF_CONNTRACK
 diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 8231a7a..7176d7f 100644
+index 816275b..671f767 100644
 --- a/net/ipv6/ip6_output.c
 +++ b/net/ipv6/ip6_output.c
 @@ -607,7 +607,7 @@ int ip6_forward(struct sk_buff *skb)
@@ -3181,7 +3181,7 @@
  obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
 diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
-index f6ab6f4..f689e19 100644
+index 706d180..65d16ef 100644
 --- a/net/netfilter/nf_conntrack_core.c
 +++ b/net/netfilter/nf_conntrack_core.c
 @@ -864,9 +864,8 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
@@ -6086,7 +6086,7 @@
 +}
 diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
 new file mode 100644
-index 0000000..2cab008
+index 0000000..e4c7db9
 --- /dev/null
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
 @@ -0,0 +1,800 @@
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3002-dts-netsys2-wed-changes.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3002-dts-netsys2-wed-changes.patch
index eacae85..213c69e 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3002-dts-netsys2-wed-changes.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3002-dts-netsys2-wed-changes.patch
@@ -1,19 +1,37 @@
-From be48305fd2e3ecd9a9853f2ae11fb9432e40b299 Mon Sep 17 00:00:00 2001
+From f99c7b63e766c2ff8851a8ba6ff77f3d8bfef0d5 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Mon, 18 Sep 2023 10:55:08 +0800
-Subject: [PATCH 03/22] dts mt7986 wed changes
+Subject: [PATCH 02/24] dts netsys2 wed changes
 
 ---
- arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 33 ++++++++---------------
- arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 33 ++++++++---------------
- 2 files changed, 22 insertions(+), 44 deletions(-)
+ .../boot/dts/mediatek/mt7981-spim-nor-rfb.dts |  8 -----
+ arch/arm64/boot/dts/mediatek/mt7981.dtsi      | 21 ++++--------
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi     | 33 +++++++------------
+ arch/arm64/boot/dts/mediatek/mt7986b.dtsi     | 33 +++++++------------
+ 4 files changed, 28 insertions(+), 67 deletions(-)
 
-diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index e43c306..e5d4e12 100644
---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-@@ -58,32 +58,20 @@
- 		};
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
+index 3fa55a0..f5c70a4 100755
+--- a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
+@@ -211,11 +211,3 @@
+ &xhci {  
+         status = "okay";
+ };
+-
+-&wed {
+-	dy_txbm_enable = "true";
+-	dy_txbm_budget = <8>;
+-	txbm_init_sz = <8>;
+-	txbm_max_sz = <32>;
+-	status = "okay";
+-};
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+index 91415e4..283421a 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+@@ -90,22 +90,12 @@
+ 		#io-channel-cells = <1>;
  	};
  
 -	wed: wed@15010000 {
@@ -24,49 +42,34 @@
 -		reg = <0 0x15010000 0 0x1000>,
 -		      <0 0x15011000 0 0x1000>;
 +	wed0: wed@15010000 {
-+		compatible = "mediatek,mt7986-wed",
++		compatible = "mediatek,mt7981-wed",
 +			     "syscon";
 +		reg = <0 0x15010000 0 0x1000>;
  		interrupt-parent = <&gic>;
 -		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
 -			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- 	};
- 
--	wed2: wed2@15011000 {
--		compatible = "mediatek,wed2";
--		wed_num = <2>;
--		reg = <0 0x15010000 0 0x1000>,
--		      <0 0x15011000 0 0x1000>;
-+	wed1: wed@15011000 {
-+		compatible = "mediatek,mt7986-wed",
-+			     "syscon";
-+		reg = <0 0x15011000 0 0x1000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
 -	};
 -
 -	wdma: wdma@15104800 {
 -		compatible = "mediatek,wed-wdma";
 -		reg = <0 0x15104800 0 0x400>,
 -		      <0 0x15104c00 0 0x400>;
-+		interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
  	};
  
  	ap2woccif: ap2woccif@151A5000 {
-@@ -507,6 +495,7 @@
- 					 <&topckgen CK_TOP_CB_SGM_325M>;
+@@ -423,6 +413,7 @@
                  mediatek,ethsys = <&ethsys>;
  		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
-+		mediatek,wed = <&wed0>, <&wed1>;
+ 		mediatek,infracfg = <&topmisc>;
++		mediatek,wed = <&wed0>;
                  #reset-cells = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index 21d8357..2d2207f 100644
---- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+index 2c7e171..3a4f279 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 @@ -58,32 +58,20 @@
  		};
  	};
@@ -110,7 +113,7 @@
  	};
  
  	ap2woccif: ap2woccif@151A5000 {
-@@ -409,6 +397,7 @@
+@@ -494,6 +482,7 @@
  					 <&topckgen CK_TOP_CB_SGM_325M>;
                  mediatek,ethsys = <&ethsys>;
  		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
@@ -118,12 +121,12 @@
                  #reset-cells = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index ccaf0ad0..b2f53b13 100644
---- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-@@ -90,22 +90,12 @@
- 		#io-channel-cells = <1>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+index 26f093b..ce884f0 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+@@ -58,32 +58,20 @@
+ 		};
  	};
  
 -	wed: wed@15010000 {
@@ -134,46 +137,45 @@
 -		reg = <0 0x15010000 0 0x1000>,
 -		      <0 0x15011000 0 0x1000>;
 +	wed0: wed@15010000 {
-+		compatible = "mediatek,mt7981-wed",
++		compatible = "mediatek,mt7986-wed",
 +			     "syscon";
 +		reg = <0 0x15010000 0 0x1000>;
  		interrupt-parent = <&gic>;
 -		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
 -			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ 	};
+ 
+-	wed2: wed2@15011000 {
+-		compatible = "mediatek,wed2";
+-		wed_num = <2>;
+-		reg = <0 0x15010000 0 0x1000>,
+-		      <0 0x15011000 0 0x1000>;
++	wed1: wed@15011000 {
++		compatible = "mediatek,mt7986-wed",
++			     "syscon";
++		reg = <0 0x15011000 0 0x1000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
 -	};
 -
 -	wdma: wdma@15104800 {
 -		compatible = "mediatek,wed-wdma";
 -		reg = <0 0x15104800 0 0x400>,
 -		      <0 0x15104c00 0 0x400>;
-+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
++		interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
  	};
  
  	ap2woccif: ap2woccif@151A5000 {
-@@ -423,6 +413,7 @@
+@@ -408,6 +396,7 @@
+ 					 <&topckgen CK_TOP_CB_SGM_325M>;
                  mediatek,ethsys = <&ethsys>;
  		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
- 		mediatek,infracfg = <&topmisc>;
-+		mediatek,wed = <&wed0>;
++		mediatek,wed = <&wed0>, <&wed1>;
                  #reset-cells = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-index 3fa55a07..f5c70a4e 100755
---- a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-@@ -211,11 +211,3 @@
- &xhci {  
-         status = "okay";
- };
--
--&wed {
--	dy_txbm_enable = "true";
--	dy_txbm_budget = <8>;
--	txbm_init_sz = <8>;
--	txbm_max_sz = <32>;
--	status = "okay";
--};
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3003-add-wed.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3003-add-wed.patch
index 16c04b5..a60b6ce 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3003-add-wed.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3003-add-wed.patch
@@ -1,7 +1,7 @@
-From cdb36beeb6725bcef3faad499c017c26bc17fd4a Mon Sep 17 00:00:00 2001
+From b895d23fa63dd712191b6d223fe6c41682c7d375 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 10:56:21 +0800
-Subject: [PATCH 04/22] add wed
+Subject: [PATCH 03/24] add wed
 
 ---
  arch/arm64/boot/dts/mediatek/mt7622.dtsi      |  32 +-
@@ -13,7 +13,7 @@
  drivers/net/ethernet/mediatek/mtk_ppe.h       |  89 +-
  .../net/ethernet/mediatek/mtk_ppe_debugfs.c   |   4 +-
  .../net/ethernet/mediatek/mtk_ppe_offload.c   | 167 +++-
- drivers/net/ethernet/mediatek/mtk_wed.c       | 876 ++++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 881 ++++++++++++++++++
  drivers/net/ethernet/mediatek/mtk_wed.h       | 135 +++
  .../net/ethernet/mediatek/mtk_wed_debugfs.c   | 175 ++++
  drivers/net/ethernet/mediatek/mtk_wed_ops.c   |   8 +
@@ -21,7 +21,7 @@
  include/linux/netdevice.h                     |   7 +
  include/linux/soc/mediatek/mtk_wed.h          | 131 +++
  net/core/dev.c                                |   4 +
- 17 files changed, 2207 insertions(+), 103 deletions(-)
+ 17 files changed, 2212 insertions(+), 103 deletions(-)
  mode change 100755 => 100644 drivers/net/ethernet/mediatek/Kconfig
  mode change 100755 => 100644 drivers/net/ethernet/mediatek/Makefile
  mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -134,7 +134,7 @@
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 old mode 100755
 new mode 100644
-index 9c85e16..88b38e2
+index 20b2943..8d15399
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 @@ -21,11 +21,13 @@
@@ -151,7 +151,7 @@
  
  #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
  #include "mtk_hnat/nf_hnat_mtk.h"
-@@ -2191,6 +2193,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2356,6 +2358,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  		struct net_device *netdev = NULL;
  		dma_addr_t dma_addr = DMA_MAPPING_ERROR;
  		u64 addr64 = 0;
@@ -159,7 +159,7 @@
  		int mac = 0;
  
  		idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
-@@ -2282,6 +2285,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2444,6 +2447,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  			skb_checksum_none_assert(skb);
  		skb->protocol = eth_type_trans(skb, netdev);
  
@@ -177,7 +177,7 @@
  		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
  			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
  				if (trxd.rxd3 & RX_DMA_VTAG_V2)
-@@ -3735,7 +3749,7 @@ static int mtk_stop(struct net_device *dev)
+@@ -4177,7 +4191,7 @@ static int mtk_stop(struct net_device *dev)
  	mtk_dma_free(eth);
  
  	if (eth->soc->offload_version)
@@ -186,7 +186,7 @@
  
  	return 0;
  }
-@@ -5044,6 +5058,22 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5560,6 +5574,22 @@ static int mtk_probe(struct platform_device *pdev)
  		}
  	}
  
@@ -208,8 +208,8 @@
 +
  	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
  		for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
- 
-@@ -5170,10 +5200,11 @@ static int mtk_probe(struct platform_device *pdev)
+ 			eth->irq_pdma[i] = platform_get_irq(pdev, i);
+@@ -5720,10 +5750,11 @@ static int mtk_probe(struct platform_device *pdev)
  	}
  
  	if (eth->soc->offload_version) {
@@ -227,10 +227,10 @@
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 old mode 100755
 new mode 100644
-index a87e46d..15337d3
+index 4d3a63c..00cfe3b
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -578,6 +578,9 @@
+@@ -615,6 +615,9 @@
  #define RX_DMA_SPORT_MASK       0x7
  #define RX_DMA_SPORT_MASK_V2    0xf
  
@@ -240,7 +240,7 @@
  /* QDMA descriptor txd4 */
  #define TX_DMA_CHKSUM		(0x7 << 29)
  #define TX_DMA_TSO		BIT(28)
-@@ -1859,7 +1862,7 @@ struct mtk_eth {
+@@ -1924,7 +1927,7 @@ struct mtk_eth {
  	spinlock_t			syscfg0_lock;
  	struct timer_list		mtk_dma_monitor_timer;
  
@@ -252,7 +252,7 @@
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
 old mode 100644
 new mode 100755
-index 27b5be5..86741bf
+index 6965d98..eeaec1b
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -6,9 +6,22 @@
@@ -1262,10 +1262,10 @@
  	return rhashtable_init(&eth->flow_table, &mtk_flow_ht_params);
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
 new file mode 100644
-index 0000000..ea1cbdf
+index 0000000..affa704
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -0,0 +1,876 @@
+@@ -0,0 +1,881 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
 +
@@ -1413,16 +1413,17 @@
 +
 +		for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
 +			u32 txd_size;
++			u32 ctrl;
 +
 +			txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
 +
-+			desc->buf0 = buf_phys;
-+			desc->buf1 = buf_phys + txd_size;
-+			desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
-+						txd_size) |
-+				     FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
-+						MTK_WED_BUF_SIZE - txd_size) |
-+				     MTK_WDMA_DESC_CTRL_LAST_SEG1;
++			desc->buf0 = cpu_to_le32(buf_phys);
++			desc->buf1 = cpu_to_le32(buf_phys + txd_size);
++			ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++			       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++					  MTK_WED_BUF_SIZE - txd_size) |
++			       MTK_WDMA_DESC_CTRL_LAST_SEG1;
++			desc->ctrl = cpu_to_le32(ctrl);
 +			desc->info = 0;
 +			desc++;
 +
@@ -1453,12 +1454,14 @@
 +
 +	for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
 +		void *page = page_list[page_idx++];
++		dma_addr_t buf_addr;
 +
 +		if (!page)
 +			break;
 +
-+		dma_unmap_page(dev->hw->dev, desc[i].buf0,
-+			       PAGE_SIZE, DMA_BIDIRECTIONAL);
++		buf_addr = le32_to_cpu(desc[i].buf0);
++		dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++			       DMA_BIDIRECTIONAL);
 +		__free_page(page);
 +	}
 +
@@ -1917,7 +1920,7 @@
 +	 * WDMA RX.
 +	 */
 +
-+	BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
++	BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
 +
 +	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE))
 +		return -ENOMEM;
@@ -2082,7 +2085,7 @@
 +		return;
 +
 +	regs = syscon_regmap_lookup_by_phandle(np, NULL);
-+	if (!regs)
++	if (IS_ERR(regs))
 +		return;
 +
 +	rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops);
@@ -2093,6 +2096,8 @@
 +		goto unlock;
 +
 +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
++	if (!hw)
++		goto unlock;
 +	hw->node = np;
 +	hw->regs = regs;
 +	hw->eth = eth;
@@ -2736,10 +2741,10 @@
 +
 +#endif
 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index ef44d9a..59a3e96 100644
+index 44842a2..5305384 100644
 --- a/include/linux/netdevice.h
 +++ b/include/linux/netdevice.h
-@@ -844,6 +844,7 @@ enum net_device_path_type {
+@@ -849,6 +849,7 @@ enum net_device_path_type {
  	DEV_PATH_BRIDGE,
  	DEV_PATH_PPPOE,
  	DEV_PATH_DSA,
@@ -2747,7 +2752,7 @@
  };
  
  struct net_device_path {
-@@ -869,6 +870,12 @@ struct net_device_path {
+@@ -874,6 +875,12 @@ struct net_device_path {
  			int port;
  			u16 proto;
  		} dsa;
@@ -2898,10 +2903,10 @@
 +
 +#endif
 diff --git a/net/core/dev.c b/net/core/dev.c
-index a117bd0..1b6d42b 100644
+index 5bade26..0775e8d 100644
 --- a/net/core/dev.c
 +++ b/net/core/dev.c
-@@ -675,6 +675,10 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+@@ -758,6 +758,10 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
  		if (WARN_ON_ONCE(last_dev == ctx.dev))
  			return -1;
  	}
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
index d613ce8..37666e6 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
@@ -1,7 +1,7 @@
-From 3562f05aedc6c2d793b34b3ee3eb78e8352804c8 Mon Sep 17 00:00:00 2001
+From 3a07dcf1a402223c3d96eed88f9dcb8eac0a9362 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 10:58:32 +0800
-Subject: [PATCH 05/22] ethernet update ppe from mt7622 to mt7986
+Subject: [PATCH 04/24] ethernet update ppe from netsys1 to netsys2
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 14 ++++-
@@ -13,10 +13,10 @@
  6 files changed, 113 insertions(+), 6 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 88b38e2..bfda873 100644
+index 8d15399..45dc85f 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2285,16 +2285,27 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2447,16 +2447,27 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  			skb_checksum_none_assert(skb);
  		skb->protocol = eth_type_trans(skb, netdev);
  
@@ -45,7 +45,7 @@
  
  		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
  			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
-@@ -5396,6 +5407,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -5953,6 +5964,7 @@ static const struct mtk_soc_data mt7986_data = {
  	.required_clks = MT7986_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -54,10 +54,10 @@
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 15337d3..a385df5 100644
+index 00cfe3b..69eb112 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -130,7 +130,7 @@
+@@ -137,7 +137,7 @@
  #define MTK_GDMA_UCS_EN		BIT(20)
  #define MTK_GDMA_STRP_CRC	BIT(16)
  #define MTK_GDMA_TO_PDMA	0x0
@@ -66,7 +66,7 @@
  #define MTK_GDMA_DROP_ALL	0x7777
  
  /* GDM Egress Control Register */
-@@ -630,6 +630,11 @@
+@@ -674,6 +674,11 @@
  #define MTK_RXD4_SRC_PORT	GENMASK(21, 19)
  #define MTK_RXD4_ALG		GENMASK(31, 22)
  
@@ -79,7 +79,7 @@
  #define RX_DMA_L4_VALID		BIT(24)
  #define RX_DMA_L4_VALID_PDMA	BIT(30)		/* when PDMA is used */
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 86741bf..ef8acbc 100755
+index eeaec1b..e195fb3 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -122,7 +122,7 @@ static u32 mtk_ppe_hash_entry(struct mtk_foe_entry *e)
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index 8d605e0..458379d 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -1,7 +1,7 @@
-From 806bb7d1a0a44a92101c506564a41dc6c4b68fd0 Mon Sep 17 00:00:00 2001
+From d35e908b342bce34e01c29a07328a4a245d5d79d Mon Sep 17 00:00:00 2001
 From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
 Date: Tue, 26 Dec 2023 16:31:34 +0800
-Subject: [PATCH 06/22] flow-offload-add-mkhnat-dual-ppe-new-v2
+Subject: [PATCH 05/24] flow-offload-add-mkhnat-dual-ppe-new-v2
 
 ---
  arch/arm64/boot/dts/mediatek/mt7986a.dtsi     |  1 +
@@ -16,10 +16,10 @@
  mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_ppe_offload.c
 
 diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index e5d4e12..0c54e12 100644
+index 3a4f279..d70151b 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-@@ -496,6 +496,7 @@
+@@ -483,6 +483,7 @@
                  mediatek,ethsys = <&ethsys>;
  		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
  		mediatek,wed = <&wed0>, <&wed1>;
@@ -28,10 +28,10 @@
                  #address-cells = <1>;
                  #size-cells = <0>;
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index bfda873..ee5e0c6 100644
+index 45dc85f..07209f0 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2276,14 +2276,16 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2459,14 +2459,16 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  
  #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
  		reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
@@ -52,7 +52,7 @@
  #endif
  
  		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
-@@ -3676,8 +3683,12 @@ static int mtk_open(struct net_device *dev)
+@@ -4111,8 +4113,12 @@ static int mtk_open(struct net_device *dev)
  		regmap_write(eth->sgmii->pcs[id].regmap,
  			     SGMSYS_QPHY_PWR_STATE_CTRL, 0);
  
@@ -67,7 +67,7 @@
  
  	mtk_gdm_config(eth, mac->id, gdm_config);
  
-@@ -3759,8 +3770,10 @@ static int mtk_stop(struct net_device *dev)
+@@ -4201,8 +4207,10 @@ static int mtk_stop(struct net_device *dev)
  
  	mtk_dma_free(eth);
  
@@ -80,7 +80,7 @@
  
  	return 0;
  }
-@@ -5211,15 +5224,35 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5761,15 +5769,35 @@ static int mtk_probe(struct platform_device *pdev)
  	}
  
  	if (eth->soc->offload_version) {
@@ -124,10 +124,10 @@
  
  	for (i = 0; i < MTK_MAX_DEVS; i++) {
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index a385df5..783166d 100644
+index 69eb112..a00583f 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -130,7 +130,12 @@
+@@ -137,7 +137,12 @@
  #define MTK_GDMA_UCS_EN		BIT(20)
  #define MTK_GDMA_STRP_CRC	BIT(16)
  #define MTK_GDMA_TO_PDMA	0x0
@@ -141,7 +141,7 @@
  #define MTK_GDMA_DROP_ALL	0x7777
  
  /* GDM Egress Control Register */
-@@ -1867,7 +1872,8 @@ struct mtk_eth {
+@@ -1932,7 +1937,8 @@ struct mtk_eth {
  	spinlock_t			syscfg0_lock;
  	struct timer_list		mtk_dma_monitor_timer;
  
@@ -151,7 +151,7 @@
  	struct rhashtable		flow_table;
  };
  
-@@ -1949,9 +1955,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+@@ -2015,9 +2021,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
  int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
  void mtk_usxgmii_link_poll(struct work_struct *work);
  
@@ -165,7 +165,7 @@
 +int mtk_ppe_debugfs_init(struct mtk_eth *eth);
  #endif /* MTK_ETH_H */
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index ef8acbc..96c15b3 100755
+index e195fb3..c9ee505 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -696,7 +696,7 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
@@ -449,10 +449,10 @@
  
  	return rhashtable_init(&eth->flow_table, &mtk_flow_ht_params);
 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index 59a3e96..0967dc2 100644
+index 5305384..b2abebe 100644
 --- a/include/linux/netdevice.h
 +++ b/include/linux/netdevice.h
-@@ -1311,6 +1311,8 @@ struct tlsdev_ops;
+@@ -1316,6 +1316,8 @@ struct tlsdev_ops;
   *	rtnl_lock is not held.
   * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);
   *     Get the forwarding path to reach the real device from the HW destination address
@@ -461,7 +461,7 @@
   */
  struct net_device_ops {
  	int			(*ndo_init)(struct net_device *dev);
-@@ -1510,6 +1512,8 @@ struct net_device_ops {
+@@ -1515,6 +1517,8 @@ struct net_device_ops {
  	struct devlink_port *	(*ndo_get_devlink_port)(struct net_device *dev);
  	int                     (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
                                                           struct net_device_path *path);
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3006-add-wed-tx-support-for-netsys2.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3006-add-wed-tx-support-for-netsys2.patch
index 5cfedfc..5197d21 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3006-add-wed-tx-support-for-netsys2.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3006-add-wed-tx-support-for-netsys2.patch
@@ -1,23 +1,23 @@
-From d76914437a405265b298b7b01235a7304634c567 Mon Sep 17 00:00:00 2001
+From 56e9bf306919ffb33d45951541d908cd7d21c081 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Mon, 18 Sep 2023 11:01:55 +0800
-Subject: [PATCH] add-wed-tx-support-for-mt7986
+Subject: [PATCH 06/24] add-wed-tx-support-for-netsys2
 
 ---
  arch/arm64/boot/dts/mediatek/mt7981.dtsi      |   1 +
- arch/arm64/boot/dts/mediatek/mt7986a.dtsi     |   2 +
- arch/arm64/boot/dts/mediatek/mt7986b.dtsi     |   2 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  17 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |   5 +
- drivers/net/ethernet/mediatek/mtk_wed.c       | 498 +++++++++++++-----
- drivers/net/ethernet/mediatek/mtk_wed.h       |  18 +-
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi     |   6 +-
+ arch/arm64/boot/dts/mediatek/mt7986b.dtsi     |   6 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  41 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h   |   3 -
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 525 +++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed.h       |  21 +-
  .../net/ethernet/mediatek/mtk_wed_debugfs.c   |   3 +
- drivers/net/ethernet/mediatek/mtk_wed_regs.h  | 130 ++++-
- include/linux/soc/mediatek/mtk_wed.h          |  23 +
- 10 files changed, 549 insertions(+), 150 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h  | 111 +++-
+ include/linux/soc/mediatek/mtk_wed.h          |  21 +-
+ 10 files changed, 575 insertions(+), 163 deletions(-)
 
 diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index e1b9b2c..3e0d2c0 100644
+index 283421a..cb8f4e1 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
 @@ -96,6 +96,7 @@
@@ -29,7 +29,7 @@
  
  	ap2woccif: ap2woccif@151A5000 {
 diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index 7e3101c..e9756bd 100644
+index d70151b..9c288fc 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 @@ -64,6 +64,7 @@
@@ -48,8 +48,26 @@
  	};
  
  	ap2woccif: ap2woccif@151A5000 {
+@@ -482,6 +484,7 @@
+ 					 <&topckgen CK_TOP_CB_SGM_325M>;
+                 mediatek,ethsys = <&ethsys>;
+ 		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++		mediatek,wed-pcie = <&wed_pcie>;
+ 		mediatek,wed = <&wed0>, <&wed1>;
+                 mtketh-ppe-num = <2>;
+                 #reset-cells = <1>;
+@@ -549,7 +552,8 @@
+ 	};
+ 
+ 	wed_pcie: wed_pcie@10003000 {
+-		compatible = "mediatek,wed_pcie";
++		compatible = "mediatek,wed_pcie",
++			     "syscon";
+ 		reg = <0 0x10003000 0 0x10>;
+ 	};
+ 
 diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index a780cfb..eafe314 100644
+index ce884f0..02feaa9 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
 @@ -64,6 +64,7 @@
@@ -68,11 +86,29 @@
  	};
  
  	ap2woccif: ap2woccif@151A5000 {
+@@ -396,6 +398,7 @@
+ 					 <&topckgen CK_TOP_CB_SGM_325M>;
+                 mediatek,ethsys = <&ethsys>;
+ 		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++		mediatek,wed-pcie = <&wed_pcie>;
+ 		mediatek,wed = <&wed0>, <&wed1>;
+                 #reset-cells = <1>;
+                 #address-cells = <1>;
+@@ -462,7 +465,8 @@
+ 	};
+ 
+ 	wed_pcie: wed_pcie@10003000 {
+-		compatible = "mediatek,wed_pcie";
++		compatible = "mediatek,wed_pcie",
++			     "syscon";
+ 		reg = <0 0x10003000 0 0x10>;
+ 	};
+ 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 3685926..51fe4b3 100644
+index 07209f0..268c9e7 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5091,6 +5091,7 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5476,6 +5476,7 @@ static int mtk_probe(struct platform_device *pdev)
  {
  	struct device_node *mac_np, *mux_np;
  	struct mtk_eth *eth;
@@ -80,8 +116,8 @@
  	int err, i;
  
  	eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL);
-@@ -5111,13 +5112,12 @@ static int mtk_probe(struct platform_device *pdev)
- 			return PTR_ERR(eth->sram_base);
+@@ -5498,13 +5499,12 @@ static int mtk_probe(struct platform_device *pdev)
+ 		eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET;
  	}
  
 -	if(eth->soc->has_sram) {
@@ -93,49 +129,66 @@
 +	if (unlikely(!res))
 +		return -EINVAL;
 +
-+	if(eth->soc->has_sram)
++	if (eth->soc->has_sram)
  		eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET;
 -	}
  
  	mtk_get_hwver(eth);
  
+@@ -5593,20 +5593,25 @@ static int mtk_probe(struct platform_device *pdev)
+ 		}
+ 	}
+ 
-@@ -5213,12 +5213,15 @@ static int mtk_probe(struct platform_device *pdev)
- 			MTK_WDMA1_BASE
- 		};
- 		void __iomem *wdma;
-+		u32 wdma_phy;
+-	for (i = 0;; i++) {
+-		struct device_node *np = of_parse_phandle(pdev->dev.of_node,
+-							  "mediatek,wed", i);
+-		static const u32 wdma_regs[] = {
+-			MTK_WDMA0_BASE,
+-			MTK_WDMA1_BASE
+-		};
+-		void __iomem *wdma;
++	if (eth->soc->offload_version) {
++		for (i = 0;; i++) {
++			struct device_node *np;
++			phys_addr_t wdma_phy;
++			u32 wdma_base;
  
- 		if (!np || i >= ARRAY_SIZE(wdma_regs))
- 			break;
+-		if (!np || i >= ARRAY_SIZE(wdma_regs))
+-			break;
++			if (i >= ARRAY_SIZE(eth->soc->reg_map->wdma_base))
++				break;
  
- 		wdma = eth->base + wdma_regs[i];
+-		wdma = eth->base + wdma_regs[i];
 -		mtk_wed_add_hw(np, eth, wdma, i);
-+		wdma_phy = res->start + wdma_regs[i];
++			np = of_parse_phandle(pdev->dev.of_node,
++					      "mediatek,wed", i);
++			if (!np)
++				break;
 +
-+		mtk_wed_add_hw(np, eth, wdma, wdma_phy, i);
++			wdma_base = eth->soc->reg_map->wdma_base[i];
++			wdma_phy = res ? res->start + wdma_base : 0;
++			mtk_wed_add_hw(np, eth, eth->base + wdma_base,
++				       wdma_phy, i);
++		}
  	}
  
  	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index b714c27..e9d88f1 100644
+index a00583f..9099dea 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -593,8 +593,13 @@
+@@ -620,9 +620,6 @@
  #define RX_DMA_SPORT_MASK       0x7
  #define RX_DMA_SPORT_MASK_V2    0xf
  
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WDMA0_BASE		0x4800
-+#define MTK_WDMA1_BASE		0x4c00
-+#else
- #define MTK_WDMA0_BASE		0x2800
- #define MTK_WDMA1_BASE		0x2c00
-+#endif
- 
+-#define MTK_WDMA0_BASE		0x2800
+-#define MTK_WDMA1_BASE		0x2c00
+-
  /* QDMA descriptor txd4 */
  #define TX_DMA_CHKSUM		(0x7 << 29)
+ #define TX_DMA_TSO		BIT(28)
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index ea1cbdf..948f013 100644
+index affa704..02e06a8 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
 @@ -18,15 +18,6 @@
@@ -154,37 +207,44 @@
  static struct mtk_wed_hw *hw_list[2];
  static DEFINE_MUTEX(hw_lock);
  
-@@ -80,14 +71,19 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
- static struct mtk_wed_hw *
+@@ -81,11 +72,31 @@ static struct mtk_wed_hw *
  mtk_wed_assign(struct mtk_wed_device *dev)
  {
--	struct mtk_wed_hw *hw;
+ 	struct mtk_wed_hw *hw;
 +	int i;
 +
-+	for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
-+		struct mtk_wed_hw *hw = hw_list[i];
++	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
++		hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
++		if (!hw)
++			return NULL;
 +
-+		if (!hw || hw->wed_dev)
-+			continue;
++		if (!hw->wed_dev)
++			goto out;
++
++		if (hw->version == 1)
++			return NULL;
++
++		/* MT7986 WED devices do not have any pcie slot restrictions */
++	}
++	/* MT7986 PCIE or AXI */
++	for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
++		hw = hw_list[i];
++		if (hw && !hw->wed_dev)
++			goto out;
++	}
  
 -	hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
 -	if (!hw || hw->wed_dev)
 -		return NULL;
-+		hw->wed_dev = dev;
-+		return hw;
-+	}
- 
--	hw->wed_dev = dev;
--	return hw;
 +	return NULL;
- }
  
- static int
-@@ -96,19 +92,27 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 	struct mtk_wdma_desc *desc;
++out:
+ 	hw->wed_dev = dev;
+ 	return hw;
+ }
+@@ -97,11 +108,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
  	dma_addr_t desc_phys;
  	void **page_list;
-+	u32 last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG1;
  	int token = dev->wlan.token_start;
 -	int ring_size;
 -	int n_pages;
@@ -193,130 +253,65 @@
 +	int i;
 +
 +
-+	if (dev->ver == MTK_WED_V1) {
++	if (dev->hw->version == 1)
 +		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
-+	} else {
++	else
 +		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
 +			    MTK_WED_WDMA_RING_SIZE * 2;
-+		last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG0;
-+	}
  
 -	ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
  	n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
  
  	page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
- 	if (!page_list)
- 		return -ENOMEM;
- 
--	dev->buf_ring.size = ring_size;
-+	dev->buf_ring.size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
- 	dev->buf_ring.pages = page_list;
+@@ -151,10 +167,17 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
  
- 	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-@@ -154,7 +158,7 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- 						txd_size) |
- 				     FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
- 						MTK_WED_BUF_SIZE - txd_size) |
--				     MTK_WDMA_DESC_CTRL_LAST_SEG1;
-+						last_seg;
+ 			desc->buf0 = cpu_to_le32(buf_phys);
+ 			desc->buf1 = cpu_to_le32(buf_phys + txd_size);
+-			ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+-			       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
+-					  MTK_WED_BUF_SIZE - txd_size) |
+-			       MTK_WDMA_DESC_CTRL_LAST_SEG1;
++
++			if (dev->hw->version == 1)
++				ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++				       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++						  MTK_WED_BUF_SIZE - txd_size) |
++				       MTK_WDMA_DESC_CTRL_LAST_SEG1;
++			else
++				ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++				       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
++						  MTK_WED_BUF_SIZE - txd_size) |
++				       MTK_WDMA_DESC_CTRL_LAST_SEG0;
+ 			desc->ctrl = cpu_to_le32(ctrl);
  			desc->info = 0;
  			desc++;
- 
-@@ -202,12 +206,12 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
- }
- 
- static void
--mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
-+mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
- {
+@@ -210,7 +233,7 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
  	if (!ring->desc)
  		return;
  
 -	dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc),
-+	dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc) * scale,
++	dma_free_coherent(dev->hw->dev, ring->size * ring->desc_size,
  			  ring->desc, ring->desc_phys);
  }
  
-@@ -217,9 +221,69 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- 	int i;
+@@ -230,6 +253,9 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ {
+ 	u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
  
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
--		mtk_wed_free_ring(dev, &dev->tx_ring[i]);
-+		mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
--		mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
-+		mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
-+}
-+
-+static void
-+mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
-+{
-+	u32 wdma_mask;
-+
-+	wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
-+
-+	/* wed control cr set */
-+	wed_set(dev, MTK_WED_CTRL,
-+		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-+		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
-+		MTK_WED_CTRL_WED_TX_BM_EN |
-+		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-+
-+	if (dev->ver == MTK_WED_V1) {
-+		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
-+			MTK_WED_PCIE_INT_TRIGGER_STATUS);
-+
-+		wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
-+			MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
-+			MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
-+
-+		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+			MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+	} else {
-+		/* initail tx interrupt trigger */
-+		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
-+			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
-+			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
-+			MTK_WED_WPDMA_INT_CTRL_TX1_DONE_EN |
-+			MTK_WED_WPDMA_INT_CTRL_TX1_DONE_CLR |
-+			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX0_DONE_TRIG,
-+				   dev->wlan.tx_tbit[0]) |
-+			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
-+				   dev->wlan.tx_tbit[1]));
++	if (dev->hw->version == 1)
++		mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
 +
-+		/* initail txfree interrupt trigger */
-+		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
-+			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
-+			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
-+			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
-+				    dev->wlan.txfree_tbit));
-+	}
-+	/* initail wdma interrupt agent */
-+	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
-+	if (dev->ver == MTK_WED_V1) {
-+		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
-+	} else {
-+		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
-+		wed_set(dev, MTK_WED_WDMA_INT_CTRL,
-+			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
-+
-+	}
-+
-+	wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-+	wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
-+	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
-+	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
- }
+ 	if (!dev->hw->num_flows)
+ 		mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
  
- static void
-@@ -234,10 +298,95 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+@@ -237,10 +263,57 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
  	wed_r32(dev, MTK_WED_EXT_INT_MASK);
  }
  
 +static void
-+mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
++mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
 +{
-+	if (en) {
++	if (enable) {
 +		wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
 +		wed_w32(dev, MTK_WED_TXP_DW1,
 +			FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
@@ -328,43 +323,6 @@
 +}
 +
 +static void
-+mtk_wed_dma_enable(struct mtk_wed_device *dev)
-+{
-+	wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+		MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+
-+	wed_set(dev, MTK_WED_GLO_CFG,
-+		MTK_WED_GLO_CFG_TX_DMA_EN |
-+		MTK_WED_GLO_CFG_RX_DMA_EN);
-+	wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
-+		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-+	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+		MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+
-+	wdma_set(dev, MTK_WDMA_GLO_CFG,
-+		 MTK_WDMA_GLO_CFG_TX_DMA_EN |
-+		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
-+		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
-+
-+	if (dev->ver == MTK_WED_V1) {
-+		wdma_set(dev, MTK_WDMA_GLO_CFG,
-+			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
-+	} else {
-+		wed_set(dev, MTK_WED_WPDMA_CTRL,
-+			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
-+
-+		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
-+			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-+
-+		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
-+			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
-+			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
-+	}
-+}
-+
-+static void
 +mtk_wed_dma_disable(struct mtk_wed_device *dev)
 +{
 +	wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
@@ -383,7 +341,7 @@
 +		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
 +		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0);
 +
-+	if (dev->ver == MTK_WED_V1) {
++	if (dev->hw->version == 1) {
 +		regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
 +		wdma_m32(dev, MTK_WDMA_GLO_CFG,
 +			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0);
@@ -391,6 +349,8 @@
 +		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
 +			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
 +			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++
++		mtk_wed_set_512_support (dev, false)
 +	}
 +}
 +
@@ -400,13 +360,10 @@
 -	regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
 +	mtk_wed_dma_disable(dev);
 +
-+	if (dev->ver > MTK_WED_V1)
-+		mtk_wed_set_512_support(dev, false);
-+
  	mtk_wed_set_ext_int(dev, false);
  
  	wed_clr(dev, MTK_WED_CTRL,
-@@ -245,26 +394,18 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+@@ -248,26 +321,18 @@ mtk_wed_stop(struct mtk_wed_device *dev)
  		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
  		MTK_WED_CTRL_WED_TX_BM_EN |
  		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
@@ -435,7 +392,7 @@
  	struct mtk_wed_hw *hw = dev->hw;
  
  	mutex_lock(&hw_lock);
-@@ -279,11 +420,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -282,11 +347,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
  	mtk_wed_free_buffer(dev);
  	mtk_wed_free_tx_rings(dev);
  
@@ -444,7 +401,7 @@
 -				   BIT(hw->index), BIT(hw->index));
 +	if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
 +		wlan_node = dev->wlan.pci_dev->dev.of_node;
-+		if (of_dma_is_coherent(wlan_node))
++		if (of_dma_is_coherent(wlan_node) && hw->hifsys)
 +			regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
 +					   BIT(hw->index), BIT(hw->index));
 +	}
@@ -454,31 +411,25 @@
  	    hw->eth->dma_dev != hw->eth->dev)
  		mtk_eth_set_dma_device(hw->eth, hw->eth->dev);
  
-@@ -294,15 +438,87 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -297,14 +365,76 @@ mtk_wed_detach(struct mtk_wed_device *dev)
  	mutex_unlock(&hw_lock);
  }
  
++#define PCIE_BASE_ADDR0 0x11280000
 +static void
 +mtk_wed_bus_init(struct mtk_wed_device *dev)
 +{
-+#define PCIE_BASE_ADDR0 0x11280000
-+
-+	if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
-+		struct device_node *node;
-+		void __iomem * base_addr;
-+		u32 value = 0;
++	switch (dev->wlan.bus_type) {
++	case MTK_BUS_TYPE_PCIE: {
++		struct device_node *np = dev->hw->eth->dev->of_node;
++		struct regmap *regs;
 +
-+		node = of_parse_phandle(dev->hw->node, "mediatek,wed_pcie", 0);
-+		if (!node) {
-+			pr_err("%s: no wed_pcie node\n", __func__);
-+			return;
-+		}
-+
-+		base_addr = of_iomap(node, 0);
++		regs = syscon_regmap_lookup_by_phandle(np,
++						       "mediatek,wed-pcie");
++		if (IS_ERR(regs))
++			break;
 +
-+		value = readl(base_addr);
-+		value |= BIT(0);
-+		writel(value, base_addr);
++		regmap_update_bits(regs, 0, BIT(0), BIT(0));
 +
 +		wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
 +			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
@@ -489,40 +440,40 @@
 +			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
 +		wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
 +
-+		value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-+		value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
 +		wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
 +		wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
 +
-+		value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-+		value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
-+
 +		/* pcie interrupt status trigger register */
 +		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
 +		wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
 +
 +		/* pola setting */
-+		value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
 +		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
 +			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
-+	} else if (dev->wlan.bus_type == MTK_BUS_TYPE_AXI) {
++		break;
++	}
++	case MTK_BUS_TYPE_AXI:
 +		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
 +			MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
 +			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
++		break;
++	default:
++		break;
 +	}
-+	return;
 +}
 +
 +static void
 +mtk_wed_set_wpdma(struct mtk_wed_device *dev)
 +{
-+	if (dev->ver > MTK_WED_V1) {
++	if (dev->hw->version == 1) {
++		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
++	} else {
++		mtk_wed_bus_init(dev);
++
 +		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_int);
 +		wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK,  dev->wlan.wpdma_mask);
 +		wed_w32(dev, MTK_WED_WPDMA_CFG_TX,  dev->wlan.wpdma_tx);
 +		wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE,  dev->wlan.wpdma_txfree);
-+	} else {
-+		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
 +	}
 +}
 +
@@ -534,21 +485,16 @@
  
  	mtk_wed_stop(dev);
  	mtk_wed_reset(dev, MTK_WED_RESET_WED);
- 
-+	if (dev->ver > MTK_WED_V1)
-+		mtk_wed_bus_init(dev);
-+
 +	mtk_wed_set_wpdma(dev);
-+
+ 
  	mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
  	       MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
- 	       MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-@@ -311,30 +527,54 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -314,14 +444,30 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
  	      MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
  	wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
  
 -	wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO_PRERES);
-+	if (dev->ver == MTK_WED_V1) {
++	if (dev->hw->version == 1) {
 +		u32 offset;
 +		offset = dev->hw->index ? 0x04000400 : 0;
 +		wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
@@ -557,7 +503,8 @@
 -	offset = dev->hw->index ? 0x04000400 : 0;
 -	wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
 -	wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
-+		wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index));
++		wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++			MTK_PCIE_BASE(dev->hw->index));
 +	} else {
 +		wed_w32(dev, MTK_WED_WDMA_CFG_BASE, dev->hw->wdma_phy);
 +		wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_ETH_DMAD_FMT);
@@ -579,44 +526,62 @@
  }
  
  static void
- mtk_wed_hw_init(struct mtk_wed_device *dev)
- {
-+	int size = dev->buf_ring.size;
-+	int rev_size = MTK_WED_TX_RING_SIZE / 2;
-+	int thr = 1;
-+
- 	if (dev->init_done)
- 		return;
+@@ -332,46 +478,79 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
  
  	dev->init_done = true;
  	mtk_wed_set_ext_int(dev, false);
-+
-+	if (dev->ver > MTK_WED_V1) {
-+		size = MTK_WED_WDMA_RING_SIZE * 2 + dev->buf_ring.size;
-+		rev_size = size;
-+		thr = 0;
-+	}
-+
- 	wed_w32(dev, MTK_WED_TX_BM_CTRL,
- 		MTK_WED_TX_BM_CTRL_PAUSE |
+-	wed_w32(dev, MTK_WED_TX_BM_CTRL,
+-		MTK_WED_TX_BM_CTRL_PAUSE |
 -		FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
 -			   dev->buf_ring.size / 128) |
 -		FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
 -			   MTK_WED_TX_RING_SIZE / 256));
-+		FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
-+		FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
  
  	wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
  
-@@ -347,28 +587,38 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+-	wed_w32(dev, MTK_WED_TX_BM_TKID,
+-		FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+-			   dev->wlan.token_start) |
+-		FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+-			   dev->wlan.token_start + dev->wlan.nbuf - 1));
+-
  	wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
  
- 	wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+-	wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
 -		FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
-+		FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr) |
- 		MTK_WED_TX_BM_DYN_THR_HI);
- 
-+	if (dev->ver > MTK_WED_V1) {
+-		MTK_WED_TX_BM_DYN_THR_HI);
++	if (dev->hw->version == 1) {
++		wed_w32(dev, MTK_WED_TX_BM_CTRL,
++			MTK_WED_TX_BM_CTRL_PAUSE |
++			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
++				   dev->buf_ring.size / 128) |
++			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
++				   MTK_WED_TX_RING_SIZE / 256));
++		wed_w32(dev, MTK_WED_TX_BM_TKID,
++			FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++				   dev->wlan.token_start) |
++			FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++				   dev->wlan.token_start +
++				   dev->wlan.nbuf - 1));
++		wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
++			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
++			MTK_WED_TX_BM_DYN_THR_HI);
++	} else {
++		wed_w32(dev, MTK_WED_TX_BM_CTRL,
++			MTK_WED_TX_BM_CTRL_PAUSE |
++			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
++				   dev->buf_ring.size / 128) |
++			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
++				   dev->buf_ring.size / 128));
++		wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
++			FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++				   dev->wlan.token_start) |
++			FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++				   dev->wlan.token_start +
++				   dev->wlan.nbuf - 1));
++		wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
++			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) |
++			MTK_WED_TX_BM_DYN_THR_HI_V2);
 +		wed_w32(dev, MTK_WED_TX_TKID_CTRL,
 +			MTK_WED_TX_TKID_CTRL_PAUSE |
 +			FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
@@ -627,21 +592,27 @@
 +			FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
 +			MTK_WED_TX_TKID_DYN_THR_HI);
 +	}
+ 
  	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
  
 -	wed_set(dev, MTK_WED_CTRL,
 -		MTK_WED_CTRL_WED_TX_BM_EN |
 -		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
--
- 	wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
-+	if (dev->ver > MTK_WED_V1)
++	if (dev->hw->version == 1)
++		wed_set(dev, MTK_WED_CTRL,
++			MTK_WED_CTRL_WED_TX_BM_EN |
++			MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
++	else
 +		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+ 
+ 	wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
  }
  
  static void
 -mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size)
-+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size)
  {
++	void *head = (void *)ring->desc;
  	int i;
  
  	for (i = 0; i < size; i++) {
@@ -649,136 +620,228 @@
 -		desc[i].ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
 -		desc[i].buf1 = 0;
 -		desc[i].info = 0;
++		struct mtk_wdma_desc *desc;
++		desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size);
 +		desc->buf0 = 0;
 +		desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
 +		desc->buf1 = 0;
 +		desc->info = 0;
-+		desc += scale;
  	}
  }
  
-@@ -424,7 +674,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 		if (!desc)
+@@ -422,12 +601,10 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) {
+-		struct mtk_wdma_desc *desc = dev->tx_ring[i].desc;
+-
+-		if (!desc)
++		if (!dev->tx_ring[i].desc)
  			continue;
  
 -		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE);
-+		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver);
++		mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE);
  	}
  
  	if (mtk_wed_poll_busy(dev))
-@@ -481,16 +731,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -484,16 +661,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  
  static int
  mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
 -		   int size)
-+		   int size, int scale)
++		   int size, u32 desc_size)
  {
- 	ring->desc = dma_alloc_coherent(dev->hw->dev,
+-	ring->desc = dma_alloc_coherent(dev->hw->dev,
 -					size * sizeof(*ring->desc),
-+					size * sizeof(*ring->desc) * scale,
++	ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size,
  					&ring->desc_phys, GFP_KERNEL);
  	if (!ring->desc)
  		return -ENOMEM;
  
++	ring->desc_size = desc_size;
  	ring->size = size;
 -	mtk_wed_ring_reset(ring->desc, size);
-+	mtk_wed_ring_reset(ring->desc, size, scale);
++	mtk_wed_ring_reset(ring, size);
  
  	return 0;
  }
-@@ -500,7 +750,7 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -501,9 +678,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+ static int
+ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
  {
++	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
  	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
  
 -	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE))
-+	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, dev->ver))
++	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size))
  		return -ENOMEM;
  
  	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
-@@ -521,60 +771,36 @@ static void
- mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -521,43 +699,63 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ }
+ 
+ static void
+-mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
  {
- 	u32 wdma_mask;
+-	u32 wdma_mask;
 -	u32 val;
- 	int i;
- 
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- 		if (!dev->tx_wdma[i].desc)
- 			mtk_wed_wdma_ring_setup(dev, i, 16);
- 
+-	int i;
+-
+-	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+-		if (!dev->tx_wdma[i].desc)
+-			mtk_wed_wdma_ring_setup(dev, i, 16);
+-
 -	wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
+-
+-	mtk_wed_hw_init(dev);
++	u32 wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
  
- 	mtk_wed_hw_init(dev);
++	/* wed control cr set */
+ 	wed_set(dev, MTK_WED_CTRL,
+ 		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
+ 		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
+ 		MTK_WED_CTRL_WED_TX_BM_EN |
+ 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
  
--	wed_set(dev, MTK_WED_CTRL,
--		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
--		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
--		MTK_WED_CTRL_WED_TX_BM_EN |
--		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
--
 -	wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, MTK_WED_PCIE_INT_TRIGGER_STATUS);
--
++	if (dev->hw->version == 1) {
++		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
++			MTK_WED_PCIE_INT_TRIGGER_STATUS);
+ 
 -	wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
 -		MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
 -		MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
-+	mtk_wed_set_int(dev, irq_mask);
- 
+-
 -	wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
 -		MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
--
--	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
++		wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
++			MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
++			MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
+ 
++		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
++	} else {
++		/* initail tx interrupt trigger */
++		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
++			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
++			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
++			MTK_WED_WPDMA_INT_CTRL_TX1_DONE_EN |
++			MTK_WED_WPDMA_INT_CTRL_TX1_DONE_CLR |
++			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX0_DONE_TRIG,
++				   dev->wlan.tx_tbit[0]) |
++			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
++				   dev->wlan.tx_tbit[1]));
++
++		/* initail txfree interrupt trigger */
++		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
++			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
++			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
++			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
++				    dev->wlan.txfree_tbit));
++
++		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
++		wed_set(dev, MTK_WED_WDMA_INT_CTRL,
++			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
++	}
++	/* initail wdma interrupt agent */
+ 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
 -	wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
--
--	wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
--	wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
  
--	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
--	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
-+	mtk_wed_set_ext_int(dev, true);
+ 	wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
+ 	wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
+-
+ 	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
+ 	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
++}
++
++static void
++mtk_wed_dma_enable(struct mtk_wed_device *dev)
++{
++	wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
++		MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
  
--	wed_set(dev, MTK_WED_GLO_CFG,
--		MTK_WED_GLO_CFG_TX_DMA_EN |
--		MTK_WED_GLO_CFG_RX_DMA_EN);
--	wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
--		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
--		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
--	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
--		MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+	if (dev->ver == MTK_WED_V1) {
-+		u32 val;
+ 	wed_set(dev, MTK_WED_GLO_CFG,
+ 		MTK_WED_GLO_CFG_TX_DMA_EN |
+@@ -568,16 +766,57 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+ 		MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
  
--	mtk_wed_set_ext_int(dev, true);
++	wdma_set(dev, MTK_WDMA_GLO_CFG,
++		 MTK_WDMA_GLO_CFG_TX_DMA_EN |
++		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
++
++	if (dev->hw->version == 1) {
++		wdma_set(dev, MTK_WDMA_GLO_CFG,
++			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
++	} else {
++		wed_set(dev, MTK_WED_WPDMA_CTRL,
++			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++
++		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++
++		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
++			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
++			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++	}
++}
++
++static void
++mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++{
++	u32 wdma_mask;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
++		if (!dev->tx_wdma[i].desc)
++			mtk_wed_wdma_ring_setup(dev, i, 16);
++
++
++	mtk_wed_hw_init(dev);
++	mtk_wed_configure_irq(dev, irq_mask);
++
+ 	mtk_wed_set_ext_int(dev, true);
 -	val = dev->wlan.wpdma_phys |
 -	      MTK_PCIE_MIRROR_MAP_EN |
 -	      FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
-+		val = dev->wlan.wpdma_phys |
-+		      MTK_PCIE_MIRROR_MAP_EN |
-+		      FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
  
 -	if (dev->hw->index)
 -		val |= BIT(1);
 -	val |= BIT(0);
 -	regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
-+		if (dev->hw->index)
-+			val |= BIT(1);
-+		val |= BIT(0);
++	if (dev->hw->version == 1) {
++		u32 val;
++
++		val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
++		      FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
+ 
++		val |= BIT(0) | (BIT(1) * !!dev->hw->index);
 +		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
 +	} else {
 +		mtk_wed_set_512_support(dev, true);
 +	}
- 
++
 +	mtk_wed_dma_enable(dev);
  	dev->running = true;
  }
  
+@@ -586,20 +825,19 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	__releases(RCU)
+ {
+ 	struct mtk_wed_hw *hw;
++	struct device *device;
+ 	int ret = 0;
+ 
-@@ -588,15 +814,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  	RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
  			 "mtk_wed_attach without holding the RCU read lock");
  
 -	if (pci_domain_nr(dev->wlan.pci_dev->bus) > 1 ||
--	    !try_module_get(THIS_MODULE))
++	if ((dev->wlan.bus_type == MTK_WED_BUS_PCIE &&
++	     pci_domain_nr(dev->wlan.pci_dev->bus) > 1) ||
+ 	    !try_module_get(THIS_MODULE))
 -		ret = -ENODEV;
-+	if (!try_module_get(THIS_MODULE))
 +		return -ENODEV;
  
  	rcu_read_unlock();
@@ -789,55 +852,48 @@
  	mutex_lock(&hw_lock);
  
  	hw = mtk_wed_assign(dev);
-@@ -606,8 +828,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -609,8 +847,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  		goto out;
  	}
  
 -	dev_info(&dev->wlan.pci_dev->dev, "attaching wed device %d\n", hw->index);
 -
++	device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
++				       &dev->wlan.pci_dev->dev
++				       : &dev->wlan.platform_dev->dev;
++	dev_info(device, "attaching wed device %d version %d\n",
++		 hw->index, hw->version);
  	dev->hw = hw;
  	dev->dev = hw->dev;
  	dev->irq = hw->irq;
-@@ -617,6 +837,9 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	    of_dma_is_coherent(hw->eth->dev->of_node))
- 		mtk_eth_set_dma_device(hw->eth, hw->dev);
- 
-+	dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
-+			    wed_r32(dev, MTK_WED_REV_ID));
-+
- 	ret = mtk_wed_buffer_alloc(dev);
- 	if (ret) {
- 		mtk_wed_detach(dev);
-@@ -624,7 +847,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -627,7 +868,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  	}
  
  	mtk_wed_hw_init_early(dev);
 -	regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, BIT(hw->index), 0);
 +
-+	if (dev->ver == MTK_WED_V1)
++	if (hw->hifsys)
 +		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
 +				   BIT(hw->index), 0);
  
  out:
  	mutex_unlock(&hw_lock);
-@@ -651,7 +877,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+@@ -654,7 +898,8 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
  
- 	BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
+ 	BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
  
 -	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE))
-+	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1))
++	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
++			       sizeof(*ring->desc)))
  		return -ENOMEM;
  
  	if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-@@ -678,21 +904,24 @@ static int
+@@ -681,21 +926,21 @@ static int
  mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
  {
  	struct mtk_wed_ring *ring = &dev->txfree_ring;
 -	int i;
-+	int i, idx = 1;
-+
-+	if(dev->ver > MTK_WED_V1)
-+		idx = 0;
++	int i, index = dev->hw->version == 1;
  
  	/*
  	 * For txfree event handling, the same DMA ring is shared between WED
@@ -845,7 +901,7 @@
  	 * WED
  	 */
 -	ring->reg_base = MTK_WED_RING_RX(1);
-+	ring->reg_base = MTK_WED_RING_RX(idx);
++	ring->reg_base = MTK_WED_RING_RX(index);
  	ring->wpdma = regs;
  
  	for (i = 0; i < 12; i += 4) {
@@ -853,22 +909,43 @@
  
 -		wed_w32(dev, MTK_WED_RING_RX(1) + i, val);
 -		wed_w32(dev, MTK_WED_WPDMA_RING_RX(1) + i, val);
-+		wed_w32(dev, MTK_WED_RING_RX(idx) + i, val);
-+		wed_w32(dev, MTK_WED_WPDMA_RING_RX(idx) + i, val);
++		wed_w32(dev, MTK_WED_RING_RX(index) + i, val);
++		wed_w32(dev, MTK_WED_WPDMA_RING_RX(index) + i, val);
  	}
  
  	return 0;
-@@ -780,7 +1009,8 @@ void mtk_wed_flow_remove(int index)
+@@ -783,7 +1028,9 @@ void mtk_wed_flow_remove(int index)
  }
  
  void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
 -		    void __iomem *wdma, int index)
-+			void __iomem *wdma, u32 wdma_phy, int index)
++		    void __iomem *wdma, phys_addr_t wdma_phy,
++		    int index)
 +
  {
  	static const struct mtk_wed_ops wed_ops = {
  		.attach = mtk_wed_attach,
-@@ -830,21 +1060,27 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -809,16 +1056,16 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 
+ 	pdev = of_find_device_by_node(np);
+ 	if (!pdev)
+-		return;
++		goto err_of_node_put;
+ 
+ 	get_device(&pdev->dev);
+ 	irq = platform_get_irq(pdev, 0);
+ 	if (irq < 0)
+-		return;
++		goto err_put_device;
+ 
+ 	regs = syscon_regmap_lookup_by_phandle(np, NULL);
+ 	if (IS_ERR(regs))
+-		return;
++		goto err_put_device;
+ 
+ 	rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops);
+ 
+@@ -835,27 +1082,42 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  	hw->eth = eth;
  	hw->dev = &pdev->dev;
  	hw->wdma = wdma;
@@ -883,16 +960,17 @@
 -		kfree(hw);
 -		goto unlock;
 -	}
- 
--	if (!index) {
--		regmap_write(hw->mirror, 0, 0);
--		regmap_write(hw->mirror, 4, 0);
-+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
++
++	if (hw->version == 1) {
 +		hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
 +							     "mediatek,pcie-mirror");
 +		hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
 +							     "mediatek,hifsys");
-+
+ 
+-	if (!index) {
+-		regmap_write(hw->mirror, 0, 0);
+-		regmap_write(hw->mirror, 4, 0);
 +		if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) {
 +			kfree(hw);
 +			goto unlock;
@@ -907,8 +985,30 @@
  	mtk_wed_hw_add_debugfs(hw);
  
  	hw_list[index] = hw;
+ 
++	mutex_unlock(&hw_lock);
++
++	return;
++
+ unlock:
+ 	mutex_unlock(&hw_lock);
++err_put_device:
++	put_device(&pdev->dev);
++err_of_node_put:
++	of_node_put(np);
+ }
+ 
+ void mtk_wed_exit(void)
+@@ -876,6 +1138,7 @@ void mtk_wed_exit(void)
+ 		hw_list[i] = NULL;
+ 		debugfs_remove(hw->debugfs_dir);
+ 		put_device(hw->dev);
++		of_node_put(hw->node);
+ 		kfree(hw);
+ 	}
+ }
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 981ec61..9b17b74 100644
+index 981ec61..c9a20e4 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.h
 @@ -8,6 +8,19 @@
@@ -931,20 +1031,27 @@
  
  struct mtk_eth;
  
-@@ -23,6 +36,7 @@ struct mtk_wed_hw {
+@@ -18,11 +31,13 @@ struct mtk_wed_hw {
+ 	struct regmap *hifsys;
+ 	struct device *dev;
+ 	void __iomem *wdma;
++	phys_addr_t wdma_phy;
+ 	struct regmap *mirror;
+ 	struct dentry *debugfs_dir;
  	struct mtk_wed_device *wed_dev;
  	u32 debugfs_reg;
  	u32 num_flows;
-+	u32 wdma_phy;
++	u8 version;
  	char dirname[5];
  	int irq;
  	int index;
-@@ -101,14 +115,14 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+@@ -101,14 +116,16 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
  }
  
  void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
 -		    void __iomem *wdma, int index);
-+		    void __iomem *wdma, u32 wdma_phy, int index);
++		    void __iomem *wdma, phys_addr_t wdma_phy,
++		    int index);
  void mtk_wed_exit(void);
  int mtk_wed_flow_add(int index);
  void mtk_wed_flow_remove(int index);
@@ -952,7 +1059,8 @@
  static inline void
  mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
 -	       void __iomem *wdma, int index)
-+	       void __iomem *wdma, u32 wdma_phy, int index)
++	       void __iomem *wdma, phys_addr_t wdma_phy,
++	       int index)
  {
  }
  static inline void
@@ -971,26 +1079,18 @@
  	struct mtk_wed_hw *hw = s->private;
  	struct mtk_wed_device *dev = hw->wed_dev;
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 0a0465e..a9b9e2a 100644
+index 0a0465e..e66acda 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -4,9 +4,15 @@
- #ifndef __MTK_WED_REGS_H
+@@ -5,6 +5,7 @@
  #define __MTK_WED_REGS_H
  
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WDMA_DESC_CTRL_LEN1			GENMASK(13, 0)
-+#define MTK_WDMA_DESC_CTRL_LAST_SEG1		BIT(14)
-+#define MTK_WDMA_DESC_CTRL_BURST		BIT(15)
-+#else
  #define MTK_WDMA_DESC_CTRL_LEN1			GENMASK(14, 0)
++#define MTK_WDMA_DESC_CTRL_LEN1_V2		GENMASK(13, 0)
  #define MTK_WDMA_DESC_CTRL_LAST_SEG1		BIT(15)
  #define MTK_WDMA_DESC_CTRL_BURST		BIT(16)
-+#endif
  #define MTK_WDMA_DESC_CTRL_LEN0			GENMASK(29, 16)
- #define MTK_WDMA_DESC_CTRL_LAST_SEG0		BIT(30)
- #define MTK_WDMA_DESC_CTRL_DMA_DONE		BIT(31)
-@@ -18,6 +24,14 @@ struct mtk_wdma_desc {
+@@ -18,6 +19,14 @@ struct mtk_wdma_desc {
  	__le32 info;
  } __packed __aligned(4);
  
@@ -1005,7 +1105,7 @@
  #define MTK_WED_RESET					0x008
  #define MTK_WED_RESET_TX_BM				BIT(0)
  #define MTK_WED_RESET_TX_FREE_AGENT			BIT(4)
-@@ -41,6 +55,7 @@ struct mtk_wdma_desc {
+@@ -41,6 +50,7 @@ struct mtk_wdma_desc {
  #define MTK_WED_CTRL_RESERVE_EN				BIT(12)
  #define MTK_WED_CTRL_RESERVE_BUSY			BIT(13)
  #define MTK_WED_CTRL_FINAL_DIDX_READ			BIT(24)
@@ -1013,7 +1113,7 @@
  #define MTK_WED_CTRL_MIB_READ_CLEAR			BIT(28)
  
  #define MTK_WED_EXT_INT_STATUS				0x020
-@@ -49,6 +64,10 @@ struct mtk_wdma_desc {
+@@ -49,6 +59,10 @@ struct mtk_wdma_desc {
  #define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID	BIT(4)
  #define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH		BIT(8)
  #define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH		BIT(9)
@@ -1024,7 +1124,7 @@
  #define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH		BIT(12)
  #define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH		BIT(13)
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR	BIT(16)
-@@ -57,16 +76,23 @@ struct mtk_wdma_desc {
+@@ -57,16 +71,23 @@ struct mtk_wdma_desc {
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN	BIT(19)
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_BM_DMAD_COHERENT	BIT(20)
  #define MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR	BIT(21)
@@ -1051,36 +1151,21 @@
  
  #define MTK_WED_EXT_INT_MASK				0x028
  
-@@ -80,10 +106,6 @@ struct mtk_wdma_desc {
- 
+@@ -81,6 +102,7 @@ struct mtk_wdma_desc {
  #define MTK_WED_TX_BM_BASE				0x084
  
--#define MTK_WED_TX_BM_TKID				0x088
--#define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
--#define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
--
- #define MTK_WED_TX_BM_BUF_LEN				0x08c
+ #define MTK_WED_TX_BM_TKID				0x088
++#define MTK_WED_TX_BM_TKID_V2				0x0c8
+ #define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
+ #define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
  
- #define MTK_WED_TX_BM_INTF				0x09c
-@@ -93,9 +115,38 @@ struct mtk_wdma_desc {
- #define MTK_WED_TX_BM_INTF_TKID_READ			BIT(29)
+@@ -94,7 +116,25 @@ struct mtk_wdma_desc {
  
  #define MTK_WED_TX_BM_DYN_THR				0x0a0
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_TX_BM_DYN_THR_LO			GENMASK(8, 0)
-+#define MTK_WED_TX_BM_DYN_THR_HI			GENMASK(24, 16)
-+
-+#define MTK_WED_TX_BM_TKID				0x0c8
-+#define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
-+#define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
-+#else
  #define MTK_WED_TX_BM_DYN_THR_LO			GENMASK(6, 0)
++#define MTK_WED_TX_BM_DYN_THR_LO_V2			GENMASK(8, 0)
  #define MTK_WED_TX_BM_DYN_THR_HI			GENMASK(22, 16)
- 
-+#define MTK_WED_TX_BM_TKID				0x088
-+#define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
-+#define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
-+#endif
++#define MTK_WED_TX_BM_DYN_THR_HI_V2			GENMASK(24, 16)
 +
 +#define MTK_WED_TX_TKID_CTRL				0x0c0
 +#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM		GENMASK(6, 0)
@@ -1097,11 +1182,10 @@
 +#define MTK_WED_TXDP_CTRL				0x130
 +#define MTK_WED_TXDP_DW9_OVERWR				BIT(9)
 +#define MTK_WED_RX_BM_TKID_MIB				0x1cc
-+
+ 
  #define MTK_WED_INT_STATUS				0x200
  #define MTK_WED_INT_MASK				0x204
- 
-@@ -125,6 +176,7 @@ struct mtk_wdma_desc {
+@@ -125,6 +165,7 @@ struct mtk_wdma_desc {
  #define MTK_WED_RESET_IDX_RX				GENMASK(17, 16)
  
  #define MTK_WED_TX_MIB(_n)				(0x2a0 + (_n) * 4)
@@ -1109,7 +1193,7 @@
  
  #define MTK_WED_RING_TX(_n)				(0x300 + (_n) * 0x10)
  
-@@ -139,6 +191,19 @@ struct mtk_wdma_desc {
+@@ -139,6 +180,19 @@ struct mtk_wdma_desc {
  #define MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY		BIT(1)
  #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN			BIT(2)
  #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY		BIT(3)
@@ -1129,7 +1213,7 @@
  #define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE		GENMASK(5, 4)
  #define MTK_WED_WPDMA_GLO_CFG_TX_WB_DDONE		BIT(6)
  #define MTK_WED_WPDMA_GLO_CFG_BIG_ENDIAN		BIT(7)
-@@ -152,24 +217,54 @@ struct mtk_wdma_desc {
+@@ -152,24 +206,54 @@ struct mtk_wdma_desc {
  #define MTK_WED_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY		BIT(26)
  #define MTK_WED_WPDMA_GLO_CFG_OMIT_RX_INFO		BIT(27)
  #define MTK_WED_WPDMA_GLO_CFG_OMIT_TX_INFO		BIT(28)
@@ -1185,7 +1269,7 @@
  
  #define MTK_WED_WPDMA_TX_MIB(_n)			(0x5a0 + (_n) * 4)
  #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n)		(0x5d0 + (_n) * 4)
-@@ -203,14 +298,22 @@ struct mtk_wdma_desc {
+@@ -203,14 +287,22 @@ struct mtk_wdma_desc {
  #define MTK_WED_WDMA_RESET_IDX_RX			GENMASK(17, 16)
  #define MTK_WED_WDMA_RESET_IDX_DRV			GENMASK(25, 24)
  
@@ -1209,7 +1293,7 @@
  
  #define MTK_WED_WDMA_RX_MIB(_n)				(0xae0 + (_n) * 4)
  #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n)			(0xae8 + (_n) * 4)
-@@ -221,14 +324,21 @@ struct mtk_wdma_desc {
+@@ -221,14 +313,21 @@ struct mtk_wdma_desc {
  #define MTK_WED_RING_OFS_CPU_IDX			0x08
  #define MTK_WED_RING_OFS_DMA_IDX			0x0c
  
@@ -1233,21 +1317,14 @@
  #define MTK_WDMA_INT_MASK				0x228
  #define MTK_WDMA_INT_MASK_TX_DONE			GENMASK(3, 0)
 diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 7e00cca..ffd547a 100644
+index 7e00cca..4db70b0 100644
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -8,6 +8,19 @@
+@@ -8,12 +8,19 @@
  
  #define MTK_WED_TX_QUEUES		2
  
 +enum {
-+	MTK_NO_WED,
-+	MTK_WED_V1,
-+	MTK_WED_V2,
-+	MTK_WED_VMAX
-+};
-+
-+enum {
 +	MTK_BUS_TYPE_PCIE,
 +	MTK_BUS_TYPE_AXI,
 +	MTK_BUS_TYPE_MAX
@@ -1256,20 +1333,24 @@
  struct mtk_wed_hw;
  struct mtk_wdma_desc;
  
-@@ -28,6 +41,7 @@ struct mtk_wed_device {
- 	bool init_done, running;
- 	int wdma_idx;
- 	int irq;
-+	u8 ver;
+ struct mtk_wed_ring {
+ 	struct mtk_wdma_desc *desc;
+ 	dma_addr_t desc_phys;
++	u32 desc_size;
+ 	int size;
+ 
+ 	u32 reg_base;
+@@ -42,9 +49,21 @@ struct mtk_wed_device {
  
- 	struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
- 	struct mtk_wed_ring txfree_ring;
-@@ -43,8 +57,17 @@ struct mtk_wed_device {
  	/* filled by driver: */
  	struct {
- 		struct pci_dev *pci_dev;
+-		struct pci_dev *pci_dev;
++		union {
++			struct platform_device *platform_dev;
++			struct pci_dev *pci_dev;
++		};
++		enum mtk_wed_bus_tye bus_type;
 +		void __iomem *base;
-+		u32 bus_type;
  
  		u32 wpdma_phys;
 +		u32 wpdma_int;
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3007-add-wed-tx-wds-support-for-netsys2.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3007-add-wed-tx-wds-support-for-netsys2.patch
index aaa6c48..d8c1c8c 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3007-add-wed-tx-wds-support-for-netsys2.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3007-add-wed-tx-wds-support-for-netsys2.patch
@@ -1,20 +1,20 @@
-From 396ce749479219467ea3f1123d5e9a303e5051ec Mon Sep 17 00:00:00 2001
+From 7c68ae1b991064bc0904313c56b83d2f3e03ccd7 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:03:33 +0800
-Subject: [PATCH 08/22] add-wed-tx-wds-support-for-mt7986
+Subject: [PATCH 07/24] add-wed-tx-wds-support-for-netsys2
 
 ---
- drivers/net/ethernet/mediatek/mtk_wed.c      | 8 +++++++-
+ drivers/net/ethernet/mediatek/mtk_wed.c      | 6 ++++--
  drivers/net/ethernet/mediatek/mtk_wed_regs.h | 1 +
  include/linux/soc/mediatek/mtk_wed.h         | 3 +++
- 3 files changed, 11 insertions(+), 1 deletion(-)
+ 3 files changed, 8 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 0588e32..23e3dc5 100644
+index 02e06a8..ea8b2db 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -797,7 +797,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- 		val |= BIT(0);
+@@ -813,7 +813,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 		val |= BIT(0) | (BIT(1) * !!dev->hw->index);
  		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
  	} else {
 -		mtk_wed_set_512_support(dev, true);
@@ -22,31 +22,24 @@
  	}
  
  	mtk_wed_dma_enable(dev);
-@@ -809,6 +809,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	__releases(RCU)
- {
- 	struct mtk_wed_hw *hw;
-+	u16 ver;
- 	int ret = 0;
+@@ -869,9 +869,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  
- 	RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
-@@ -839,6 +840,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	mtk_wed_hw_init_early(dev);
  
- 	dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
- 			    wed_r32(dev, MTK_WED_REV_ID));
-+	if (dev->ver > MTK_WED_V1)
-+		ver = FIELD_GET(MTK_WED_REV_ID_MINOR,
-+			    wed_r32(dev, MTK_WED_REV_ID));
-+
-+	dev->rev_id = ((dev->ver << 28) | ver << 16);
+-	if (hw->hifsys)
++	if (hw->version == 1)
+ 		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ 				   BIT(hw->index), 0);
++	else
++		dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
  
- 	ret = mtk_wed_buffer_alloc(dev);
- 	if (ret) {
+ out:
+ 	mutex_unlock(&hw_lock);
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index a9b9e2a..14e0e21 100644
+index e66acda..e797e9d 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -31,6 +31,7 @@ struct mtk_wdma_desc {
+@@ -26,6 +26,7 @@ struct mtk_wdma_desc {
  #define MTK_WED_REV_ID					0x000
  #define MTK_WED_REV_ID_MAJOR				GENMASK(7, 0)
  #endif
@@ -55,18 +48,18 @@
  #define MTK_WED_RESET					0x008
  #define MTK_WED_RESET_TX_BM				BIT(0)
 diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index ffd547a..e914cb4 100644
+index 4db70b0..00036f9 100644
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -42,6 +42,7 @@ struct mtk_wed_device {
+@@ -35,6 +35,7 @@ struct mtk_wed_device {
+ 	bool init_done, running;
  	int wdma_idx;
  	int irq;
- 	u8 ver;
 +	u32 rev_id;
  
  	struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
  	struct mtk_wed_ring txfree_ring;
-@@ -72,6 +73,8 @@ struct mtk_wed_device {
+@@ -68,6 +69,8 @@ struct mtk_wed_device {
  		u16 token_start;
  		unsigned int nbuf;
  
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3008-add-wed-rx-support-for-netsys2.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3008-add-wed-rx-support-for-netsys2.patch
index 7efa9df..fd64dcf 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3008-add-wed-rx-support-for-netsys2.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3008-add-wed-rx-support-for-netsys2.patch
@@ -1,24 +1,25 @@
-From d35f304a7d0ec9612064a41b98338d9f712fbb48 Mon Sep 17 00:00:00 2001
+From fad15885ddf2f138ed3ec652b4fcd0cbdf54bf4e Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:04:53 +0800
-Subject: [PATCH 09/22] add-wed-rx-support-for-mt7896
+Subject: [PATCH 08/24] add-wed-rx-support-for-netsys2
 
 ---
+ arch/arm64/boot/dts/mediatek/mt7981.dtsi      |  23 +-
  arch/arm64/boot/dts/mediatek/mt7986a.dtsi     |  42 +-
  arch/arm64/boot/dts/mediatek/mt7986b.dtsi     |  42 +-
  drivers/net/ethernet/mediatek/Makefile        |   2 +-
- drivers/net/ethernet/mediatek/mtk_wed.c       | 639 ++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 645 ++++++++++++++++--
  drivers/net/ethernet/mediatek/mtk_wed.h       |  51 ++
  drivers/net/ethernet/mediatek/mtk_wed_ccif.c  | 133 ++++
  drivers/net/ethernet/mediatek/mtk_wed_ccif.h  |  45 ++
  .../net/ethernet/mediatek/mtk_wed_debugfs.c   |  90 +++
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c   | 586 ++++++++++++++++
- drivers/net/ethernet/mediatek/mtk_wed_mcu.h   |  96 +++
- drivers/net/ethernet/mediatek/mtk_wed_regs.h  | 144 +++-
- drivers/net/ethernet/mediatek/mtk_wed_wo.c    | 564 ++++++++++++++++
- drivers/net/ethernet/mediatek/mtk_wed_wo.h    | 324 +++++++++
- include/linux/soc/mediatek/mtk_wed.h          | 126 +++-
- 14 files changed, 2801 insertions(+), 83 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c   | 604 ++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.h   |  97 +++
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h  | 143 +++-
+ drivers/net/ethernet/mediatek/mtk_wed_wo.c    | 564 +++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_wo.h    | 325 +++++++++
+ include/linux/soc/mediatek/mtk_wed.h          | 114 +++-
+ 15 files changed, 2822 insertions(+), 98 deletions(-)
  create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.c
  create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.h
  create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c
@@ -26,8 +27,52 @@
  create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c
  create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h
 
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+index cb8f4e1..39b99d8 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+@@ -97,26 +97,29 @@
+ 		interrupt-parent = <&gic>;
+ 		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ 		mediatek,wed_pcie = <&wed_pcie>;
++		mediatek,ap2woccif = <&ap2woccif0>;
++		mediatek,wocpu_ilm = <&wocpu0_ilm>;
++		mediatek,wocpu_dlm = <&wocpu0_dlm>;
++		mediatek,wocpu_boot = <&cpu_boot>;
++		mediatek,wocpu_emi = <&wocpu0_emi>;
++		mediatek,wocpu_data = <&wocpu_data>;
+ 	};
+ 
+-	ap2woccif: ap2woccif@151A5000 {
+-		compatible = "mediatek,ap2woccif";
+-		reg = <0 0x151A5000 0 0x1000>,
+-		      <0 0x151AD000 0 0x1000>;
++	ap2woccif0: ap2woccif@151A5000 {
++		compatible = "mediatek,ap2woccif", "syscon";
++		reg = <0 0x151A5000 0 0x1000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
+-        };
++		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
++	};
+ 
+ 	wocpu0_ilm: wocpu0_ilm@151E0000 {
+ 		compatible = "mediatek,wocpu0_ilm";
+ 		reg = <0 0x151E0000 0 0x8000>;
+ 	};
+ 
+-	wocpu_dlm: wocpu_dlm@151E8000 {
++	wocpu0_dlm: wocpu_dlm@151E8000 {
+ 		compatible = "mediatek,wocpu_dlm";
+-		reg = <0 0x151E8000 0 0x2000>,
+-		      <0 0x151F8000 0 0x2000>;
++		reg = <0 0x151E8000 0 0x2000>;
+ 
+ 		resets = <&ethsysrst 0>;
+ 		reset-names = "wocpu_rst";
 diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index 3ff8994..c5dc5e8 100644
+index 9c288fc..e6f50d5 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
 @@ -65,6 +65,12 @@
@@ -98,7 +143,7 @@
  		resets = <&ethsysrst 0>;
  		reset-names = "wocpu_rst";
 diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index 043e509..bfd2a02 100644
+index 02feaa9..3bacadc 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
 @@ -65,6 +65,12 @@
@@ -168,50 +213,6 @@
  
  		resets = <&ethsysrst 0>;
  		reset-names = "wocpu_rst";
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index d34943e7..512fb5d6 100644
---- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-@@ -97,26 +97,29 @@
- 		interrupt-parent = <&gic>;
- 		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- 		mediatek,wed_pcie = <&wed_pcie>;
-+		mediatek,ap2woccif = <&ap2woccif0>;
-+		mediatek,wocpu_ilm = <&wocpu0_ilm>;
-+		mediatek,wocpu_dlm = <&wocpu0_dlm>;
-+		mediatek,wocpu_boot = <&cpu_boot>;
-+		mediatek,wocpu_emi = <&wocpu0_emi>;
-+		mediatek,wocpu_data = <&wocpu_data>;
- 	};
- 
--	ap2woccif: ap2woccif@151A5000 {
--		compatible = "mediatek,ap2woccif";
--		reg = <0 0x151A5000 0 0x1000>,
--		      <0 0x151AD000 0 0x1000>;
-+	ap2woccif0: ap2woccif@151A5000 {
-+		compatible = "mediatek,ap2woccif", "syscon";
-+		reg = <0 0x151A5000 0 0x1000>;
- 		interrupt-parent = <&gic>;
--		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
--			     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
--        };
-+		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
-+	};
- 
- 	wocpu0_ilm: wocpu0_ilm@151E0000 {
- 		compatible = "mediatek,wocpu0_ilm";
- 		reg = <0 0x151E0000 0 0x8000>;
- 	};
- 
--	wocpu_dlm: wocpu_dlm@151E8000 {
-+	wocpu0_dlm: wocpu_dlm@151E8000 {
- 		compatible = "mediatek,wocpu_dlm";
--		reg = <0 0x151E8000 0 0x2000>,
--		      <0 0x151F8000 0 0x2000>;
-+		reg = <0 0x151E8000 0 0x2000>;
- 
- 		resets = <&ethsysrst 0>;
- 		reset-names = "wocpu_rst";
 diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
 index 4090132..fdbb90f 100644
 --- a/drivers/net/ethernet/mediatek/Makefile
@@ -224,10 +225,10 @@
 +obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o mtk_wed_wo.o mtk_wed_mcu.o mtk_wed_ccif.o
  obj-$(CONFIG_NET_MEDIATEK_HNAT)			+= mtk_hnat/
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 23e3dc5..4b2f1a2 100644
+index ea8b2db..ad9f3d5 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -13,11 +13,19 @@
+@@ -13,10 +13,13 @@
  #include <linux/debugfs.h>
  #include <linux/iopoll.h>
  #include <linux/soc/mediatek/mtk_wed.h>
@@ -236,19 +237,12 @@
  #include "mtk_wed_regs.h"
  #include "mtk_wed.h"
  #include "mtk_ppe.h"
--
 +#include "mtk_wed_mcu.h"
 +#include "mtk_wed_wo.h"
-+
-+struct wo_cmd_ring {
-+	u32 q_base;
-+	u32 cnt;
-+	u32 unit;
-+};
+ 
  static struct mtk_wed_hw *hw_list[2];
  static DEFINE_MUTEX(hw_lock);
- 
-@@ -51,6 +59,56 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
+@@ -51,12 +54,65 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
  	wdma_m32(dev, reg, 0, mask);
  }
  
@@ -258,92 +252,107 @@
 +	wdma_m32(dev, reg, mask, 0);
 +}
 +
+ static u32
+ mtk_wed_read_reset(struct mtk_wed_device *dev)
+ {
+ 	return wed_r32(dev, MTK_WED_RESET);
+ }
+ 
 +static u32
 +mtk_wdma_read_reset(struct mtk_wed_device *dev)
 +{
 +	return wdma_r32(dev, MTK_WDMA_GLO_CFG);
 +}
 +
-+static void
++static int
 +mtk_wdma_rx_reset(struct mtk_wed_device *dev)
 +{
-+	u32 status;
-+	u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
-+	int i;
++	u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
++	int i, ret;
 +
 +	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
-+	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-+			       !(status & mask), 0, 1000))
-+		WARN_ON_ONCE(1);
++	ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
++				 !(status & mask), 0, 1000)
++	if (ret)
++		dev_err(dev->hw->dev, "rx reset failed \n");
 +
-+	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
-+		if (!dev->rx_wdma[i].desc) {
-+			wdma_w32(dev, MTK_WDMA_RING_RX(i) +
-+				 MTK_WED_RING_OFS_CPU_IDX, 0);
++	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
++		if (!dev->rx_wdma[i].desc)
++			continue;
++
++		wdma_w32(dev,
++			 MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
 +	}
 +}
 +
 +static void
 +mtk_wdma_tx_reset(struct mtk_wed_device *dev)
 +{
-+	u32 status;
-+	u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
++	u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
 +	int i;
 +
 +	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
 +	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
 +			       !(status & mask), 0, 1000))
-+		WARN_ON_ONCE(1);
++		dev_err(dev->hw->dev, "tx reset failed \n");
 +
-+	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+		if (!dev->tx_wdma[i].desc) {
-+			wdma_w32(dev, MTK_WDMA_RING_TX(i) +
-+				 MTK_WED_RING_OFS_CPU_IDX, 0);
++	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) {
++		if (!dev->tx_wdma[i].desc)
++			continue;
++
++		wdma_w32(dev,
++			 MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
 +	}
 +}
 +
- static u32
- mtk_wed_read_reset(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
  {
-@@ -68,6 +126,52 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
+@@ -68,6 +124,58 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
  		WARN_ON_ONCE(1);
  }
  
++static u32
++mtk_wed_wo_read_status(struct mtk_wed_device *dev)
++{
++	return wed_r32(dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_WO_STATUS);
++}
++
 +static void
 +mtk_wed_wo_reset(struct mtk_wed_device *dev)
 +{
 +	struct mtk_wed_wo *wo = dev->hw->wed_wo;
 +	u8 state = WO_STATE_DISABLE;
-+	u8 state_done = WOIF_DISABLE_DONE;
 +	void __iomem *reg;
-+	u32 value;
-+	unsigned long timeout = jiffies + WOCPU_TIMEOUT;
++	u32 val;
 +
 +	mtk_wdma_tx_reset(dev);
 +
 +	mtk_wed_reset(dev, MTK_WED_RESET_WED);
 +
-+	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+			     &state, sizeof(state), false);
++	mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++			     MTK_WED_WO_CMD_CHANGE_STATE, &state,
++			     sizeof(state), false);
 +
-+	do {
-+		value = wed_r32(dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_WO_STATUS);
-+	} while (value != state_done && !time_after(jiffies, timeout));
++	if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val,
++			       val == WOIF_DISABLE_DONE,
++			       100, WOCPU_TIMEOUT))
++		dev_err(dev->hw->dev, "failed to disable wed-wo\n");
 +
 +	reg = ioremap(WOCPU_MCUSYS_RESET_ADDR, 4);
-+	value = readl((void *)reg);
++	val = readl((void *)reg);
 +	switch(dev->hw->index) {
 +	case 0:
-+		value |= WOCPU_WO0_MCUSYS_RESET_MASK;
-+		writel(value, (void *)reg);
-+		value &= ~WOCPU_WO0_MCUSYS_RESET_MASK;
-+		writel(value, (void *)reg);
++		val |= WOCPU_WO0_MCUSYS_RESET_MASK;
++		writel(val, (void *)reg);
++		val &= ~WOCPU_WO0_MCUSYS_RESET_MASK;
++		writel(val, (void *)reg);
 +		break;
 +	case 1:
-+		value |= WOCPU_WO1_MCUSYS_RESET_MASK;
-+		writel(value, (void *)reg);
-+		value &= ~WOCPU_WO1_MCUSYS_RESET_MASK;
-+		writel(value, (void *)reg);
++		val |= WOCPU_WO1_MCUSYS_RESET_MASK;
++		writel(val, (void *)reg);
++		val &= ~WOCPU_WO1_MCUSYS_RESET_MASK;
++		writel(val, (void *)reg);
 +		break;
 +	default:
 +		dev_err(dev->hw->dev, "wrong mtk_wed%d\n",
@@ -358,21 +367,58 @@
  static struct mtk_wed_hw *
  mtk_wed_assign(struct mtk_wed_device *dev)
  {
-@@ -178,7 +282,7 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -102,7 +210,7 @@ mtk_wed_assign(struct mtk_wed_device *dev)
+ }
+ 
+ static int
+-mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
++mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ {
+ 	struct mtk_wdma_desc *desc;
+ 	dma_addr_t desc_phys;
+@@ -124,16 +232,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
+ 	if (!page_list)
+ 		return -ENOMEM;
+ 
+-	dev->buf_ring.size = ring_size;
+-	dev->buf_ring.pages = page_list;
++	dev->tx_buf_ring.size = ring_size;
++	dev->tx_buf_ring.pages = page_list;
+ 
+ 	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+ 				  &desc_phys, GFP_KERNEL);
+ 	if (!desc)
+ 		return -ENOMEM;
+ 
+-	dev->buf_ring.desc = desc;
+-	dev->buf_ring.desc_phys = desc_phys;
++	dev->tx_buf_ring.desc = desc;
++	dev->tx_buf_ring.desc_phys = desc_phys;
+ 
+ 	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+ 		dma_addr_t page_phys, buf_phys;
+@@ -194,11 +302,11 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
+ }
+ 
+ static void
+-mtk_wed_free_buffer(struct mtk_wed_device *dev)
++mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
  {
- 	struct mtk_wdma_desc *desc = dev->buf_ring.desc;
- 	void **page_list = dev->buf_ring.pages;
+-	struct mtk_wdma_desc *desc = dev->buf_ring.desc;
+-	void **page_list = dev->buf_ring.pages;
 -	int page_idx;
++	struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc;
++	void **page_list = dev->tx_buf_ring.pages;
 +	int ring_size, page_idx;
  	int i;
  
  	if (!page_list)
-@@ -187,7 +291,14 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -207,7 +315,14 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
  	if (!desc)
  		goto free_pagelist;
  
 -	for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
-+	if (dev->ver == MTK_WED_V1) {
++	if (dev->hw->version == 1) {
 +		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
 +	} else {
 +		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
@@ -381,201 +427,141 @@
 +
 +	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
  		void *page = page_list[page_idx++];
+ 		dma_addr_t buf_addr;
  
- 		if (!page)
-@@ -198,13 +309,49 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -220,13 +335,64 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
  		__free_page(page);
  	}
  
 -	dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc),
+-			  desc, dev->buf_ring.desc_phys);
 +	dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
- 			  desc, dev->buf_ring.desc_phys);
++			  desc, dev->tx_buf_ring.desc_phys);
  
  free_pagelist:
  	kfree(page_list);
  }
  
 +static int
-+mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
++mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
 +{
 +	struct mtk_rxbm_desc *desc;
 +	dma_addr_t desc_phys;
-+	int ring_size;
 +
-+	ring_size = dev->wlan.rx_nbuf;
-+	dev->rx_buf_ring.size = ring_size;
-+	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
++	dev->rx_buf_ring.size = dev->wlan.rx_nbuf;
++	desc = dma_alloc_coherent(dev->hw->dev,
++				  dev->wlan.rx_nbuf * sizeof(*desc),
 +				  &desc_phys, GFP_KERNEL);
 +	if (!desc)
 +		return -ENOMEM;
 +
 +	dev->rx_buf_ring.desc = desc;
 +	dev->rx_buf_ring.desc_phys = desc_phys;
-+
 +	dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt);
++
 +	return 0;
 +}
 +
 +static void
-+mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
++mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
 +{
 +	struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
-+	int ring_size = dev->rx_buf_ring.size;
 +
 +	if (!desc)
 +		return;
 +
 +	dev->wlan.release_rx_buf(dev);
 +
-+	dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
++	dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc),
 +			  desc, dev->rx_buf_ring.desc_phys);
 +}
 +
++static void
++mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev)
++{
++	wed_w32(dev, MTK_WED_RX_BM_RX_DMAD,
++		FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0,  dev->wlan.rx_size));
++
++	wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
++
++	wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
++		FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt));
++
++	wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH,
++		FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
++
++	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++}
++
  static void
- mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
+ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
  {
-@@ -226,13 +373,22 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- 		mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
+@@ -237,6 +403,13 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
+ 			  ring->desc, ring->desc_phys);
  }
  
 +static void
 +mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
 +{
-+	mtk_wed_free_rx_bm(dev);
-+	mtk_wed_free_ring(dev, &dev->rro.rro_ring, 1);
++	mtk_wed_free_rx_buffer(dev);
++	mtk_wed_free_ring(dev, &dev->rro.ring);
 +}
 +
  static void
- mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
+ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
  {
- 	u32 wdma_mask;
- 
- 	wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
--
-+	if (dev->ver > MTK_WED_V1)
-+		wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
-+					GENMASK(1, 0));
- 	/* wed control cr set */
- 	wed_set(dev, MTK_WED_CTRL,
- 		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-@@ -251,7 +407,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- 			MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
- 	} else {
--		/* initail tx interrupt trigger */
-+
- 		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
- 			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
- 			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
-@@ -262,22 +418,30 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
- 				   dev->wlan.tx_tbit[1]));
+@@ -244,8 +417,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
  
--		/* initail txfree interrupt trigger */
- 		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
- 			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
- 			MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
- 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
- 				    dev->wlan.txfree_tbit));
-+
-+		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
-+			MTK_WED_WPDMA_INT_CTRL_RX0_EN |
-+			MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
-+			MTK_WED_WPDMA_INT_CTRL_RX1_EN |
-+			MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
-+			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
-+				   dev->wlan.rx_tbit[0]) |
-+			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
-+				   dev->wlan.rx_tbit[1]));
- 	}
--	/* initail wdma interrupt agent */
- 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
- 	if (dev->ver == MTK_WED_V1) {
- 		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
- 	} else {
- 		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
- 		wed_set(dev, MTK_WED_WDMA_INT_CTRL,
--			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
--
-+			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,
-+				   dev->wdma_idx));
- 	}
+ 	for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
+ 		mtk_wed_free_ring(dev, &dev->tx_ring[i]);
+-	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+-		mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
++	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
++		mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
+ }
  
- 	wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-@@ -312,6 +476,40 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
+ static void
+@@ -277,6 +450,39 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
  	}
  }
  
++#define MTK_WFMDA_RX_DMA_EN	BIT(2)
 +static void
 +mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
 +{
-+#define MTK_WFMDA_RX_DMA_EN 	BIT(2)
++	u32 val;
++	int i;
 +
-+	int timeout = 3;
-+	u32 cur_idx, regs;
++	if(!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED))
++		return;
 +
-+	do {
-+		regs = MTK_WED_WPDMA_RING_RX_DATA(idx) +
-+		       MTK_WED_RING_OFS_CPU_IDX;
-+		cur_idx = wed_r32(dev, regs);
++	for (i = 0; i < 3; i++) {
++		u32 cur_idx;
++
++		cur_idx = wed_r32(dev,
++				  MTK_WED_WPDMA_RING_RX_DATA(idx) +
++				  MTK_WED_RING_OFS_CPU_IDX);
 +		if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
 +			break;
 +
 +		usleep_range(100000, 200000);
-+		timeout--;
-+	} while (timeout > 0);
-+
-+	if (timeout) {
-+		unsigned int val;
-+
-+		val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
-+			       dev->wlan.phy_base);
-+		val |= MTK_WFMDA_RX_DMA_EN;
++	}
 +
-+		wifi_w32(dev, dev->wlan.wpdma_rx_glo -
-+			 dev->wlan.phy_base, val);
-+	} else {
++	if (i == 3) {
 +		dev_err(dev->hw->dev, "mtk_wed%d: rx dma enable failed!\n",
 +			       dev->hw->index);
++		return;
 +	}
++
++	val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) |
++	      MTK_WFMDA_RX_DMA_EN;
++	wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val);
 +}
 +
  static void
- mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ mtk_wed_dma_disable(struct mtk_wed_device *dev)
  {
-@@ -336,9 +534,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- 		wdma_set(dev, MTK_WDMA_GLO_CFG,
- 			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
- 	} else {
-+		int idx = 0;
-+
- 		wed_set(dev, MTK_WED_WPDMA_CTRL,
- 			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
- 
-+		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+			MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
-+			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-+
- 		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
- 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-@@ -346,6 +550,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- 		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- 			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
- 			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
-+
-+		wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
-+			MTK_WED_WPDMA_RX_D_RX_DRV_EN |
-+			FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
-+			FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
-+				   0x2));
-+
-+		for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++)
-+			mtk_wed_check_wfdma_rx_fill(dev, idx);
- 	}
- }
- 
-@@ -363,19 +576,23 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+@@ -291,22 +497,26 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
  		MTK_WED_GLO_CFG_TX_DMA_EN |
  		MTK_WED_GLO_CFG_RX_DMA_EN);
  
@@ -586,7 +572,7 @@
 -		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0);
 +		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
  
- 	if (dev->ver == MTK_WED_V1) {
+ 	if (dev->hw->version == 1) {
  		regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
 -		wdma_m32(dev, MTK_WDMA_GLO_CFG,
 -			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0);
@@ -596,125 +582,169 @@
  		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
  			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
  			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+-
+-		mtk_wed_set_512_support (dev, false)
 +		wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
 +			MTK_WED_WPDMA_RX_D_RX_DRV_EN);
 +		wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
 +			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
  	}
++
++	mtk_wed_set_512_support (dev, false);
  }
  
-@@ -383,10 +600,12 @@ static void
- mtk_wed_stop(struct mtk_wed_device *dev)
- {
- 	mtk_wed_dma_disable(dev);
-+	mtk_wed_set_512_support(dev, false);
- 
--	if (dev->ver > MTK_WED_V1)
--		mtk_wed_set_512_support(dev, false);
--
-+	if (dev->ver > MTK_WED_V1) {
-+		wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
-+		wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
-+	}
- 	mtk_wed_set_ext_int(dev, false);
- 
- 	wed_clr(dev, MTK_WED_CTRL,
-@@ -395,6 +614,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
- 		MTK_WED_CTRL_WED_TX_BM_EN |
- 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
- 
-+	if (dev->ver > MTK_WED_V1) {
-+		wed_clr(dev, MTK_WED_CTRL,
-+			MTK_WED_CTRL_WED_RX_BM_EN);
-+	}
-+
- 	wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
- 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
+ static void
+@@ -327,6 +537,14 @@ mtk_wed_stop(struct mtk_wed_device *dev)
  	wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-@@ -417,10 +641,21 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ 	wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
+ 	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
++
++	if (dev->hw->version == 1)
++		return;
++
++	wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
++	wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
++	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++
+ }
+ 
+ static void
+@@ -344,10 +562,23 @@ mtk_wed_detach(struct mtk_wed_device *dev)
  
  	mtk_wed_reset(dev, MTK_WED_RESET_WED);
  
-+	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
-+	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
-+	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+-	mtk_wed_free_buffer(dev);
++	if (mtk_wed_get_rx_capa(dev)) {
++		wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
++		wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
++		wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
++	}
 +
- 	mtk_wed_free_buffer(dev);
++	mtk_wed_free_tx_buffer(dev);
  	mtk_wed_free_tx_rings(dev);
-+	if (dev->ver > MTK_WED_V1) {
+ 
+-	if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
++	if (mtk_wed_get_rx_capa(dev)) {
 +		mtk_wed_wo_reset(dev);
 +		mtk_wed_free_rx_rings(dev);
 +		mtk_wed_wo_exit(hw);
++		mtk_wdma_rx_reset(dev);
 +	}
 +
-+	mtk_wdma_rx_reset(dev);
- 
--	if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
 +	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
  		wlan_node = dev->wlan.pci_dev->dev.of_node;
- 		if (of_dma_is_coherent(wlan_node))
+ 		if (of_dma_is_coherent(wlan_node) && hw->hifsys)
  			regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
-@@ -443,7 +678,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+@@ -370,7 +601,7 @@ static void
+ mtk_wed_bus_init(struct mtk_wed_device *dev)
  {
- #define PCIE_BASE_ADDR0 0x11280000
- 
--	if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
-+	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
- 		struct device_node *node;
- 		void __iomem * base_addr;
- 		u32 value = 0;
-@@ -477,7 +712,6 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- 		value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
- 		value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
- 
--		/* pcie interrupt status trigger register */
- 		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
- 		wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+ 	switch (dev->wlan.bus_type) {
+-	case MTK_BUS_TYPE_PCIE: {
++	case MTK_WED_BUS_PCIE: {
+ 		struct device_node *np = dev->hw->eth->dev->of_node;
+ 		struct regmap *regs;
  
-@@ -485,7 +719,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- 		value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
- 		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+@@ -402,7 +633,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
  			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
--	} else if (dev->wlan.bus_type == MTK_BUS_TYPE_AXI) {
-+	} else if (dev->wlan.bus_type == MTK_WED_BUS_AXI) {
+ 		break;
+ 	}
+-	case MTK_BUS_TYPE_AXI:
++	case MTK_WED_BUS_AXI:
  		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
  			MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
  			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
-@@ -501,6 +735,9 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+@@ -424,6 +655,8 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
  		wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK,  dev->wlan.wpdma_mask);
  		wed_w32(dev, MTK_WED_WPDMA_CFG_TX,  dev->wlan.wpdma_tx);
  		wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE,  dev->wlan.wpdma_txfree);
-+
 +		wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG,  dev->wlan.wpdma_rx_glo);
 +		wed_w32(dev, MTK_WED_WPDMA_RX_RING,  dev->wlan.wpdma_rx);
- 	} else {
- 		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
  	}
-@@ -549,24 +786,92 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
- 			FIELD_PREP(MTK_WED_WDMA_OFST1_RX_CTRL,
- 				   MTK_WDMA_RING_RX(0)));
- 	}
-+}
+ }
  
-+static void
-+mtk_wed_rx_bm_hw_init(struct mtk_wed_device *dev)
+@@ -470,6 +703,141 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+ 
+ }
+ 
++static int
++mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
++		   int size)
 +{
-+	wed_w32(dev, MTK_WED_RX_BM_RX_DMAD,
-+		FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0,  dev->wlan.rx_size));
++	ring->desc = dma_alloc_coherent(dev->hw->dev,
++					size * sizeof(*ring->desc),
++					&ring->desc_phys, GFP_KERNEL);
++	if (!ring->desc)
++		return -ENOMEM;
 +
-+	wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
++	ring->desc_size = sizeof(*ring->desc);
++	ring->size = size;
++	memset(ring->desc, 0, size);
 +
-+	wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
-+		FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt));
++	return 0;
++}
 +
-+	wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH,
-+		FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
++#define MTK_WED_MIOD_COUNT	(MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT)
++static int
++mtk_wed_rro_alloc(struct mtk_wed_device *dev)
++{
++	struct device_node *np, *node = dev->hw->node;
++	struct mtk_wed_ring *ring;
++	struct resource res;
++	int ret;
 +
-+	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
- }
- 
- static void
--mtk_wed_hw_init(struct mtk_wed_device *dev)
++	np = of_parse_phandle(node, "mediatek,wocpu_dlm", 0);
++	if (!np)
++		return -ENODEV;
++
++	ret = of_address_to_resource(np, 0, &res);
++	if (ret)
++		return ret;
++
++	dev->rro.rro_desc = ioremap(res.start, resource_size(&res));
++
++	ring = &dev->rro.ring;
++
++	dev->rro.miod_phys = res.start;
++	dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys;
++
++	if (mtk_wed_rro_ring_alloc(dev, ring, MTK_WED_RRO_QUE_CNT))
++		return -ENOMEM;
++
++	return 0;
++}
++
++static int
++mtk_wed_rro_cfg(struct mtk_wed_device *dev)
++{
++	struct mtk_wed_wo *wo = dev->hw->wed_wo;
++	struct {
++		struct {
++			__le32 base;
++			__le32 cnt;
++			__le32 unit;
++		} ring[2];
++
++		__le32 wed;
++		u8 version;
++	} req = {
++		.ring[0] = {
++			.base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE),
++			.cnt = cpu_to_le32(MTK_WED_MIOD_CNT),
++			.unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT),
++		},
++		.ring[1] = {
++			.base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE +
++					    MTK_WED_MIOD_COUNT),
++			.cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT),
++			.unit = cpu_to_le32(4),
++		},
++	};
++
++	return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
++				    &req, sizeof(req), true);
++}
++
++static void
 +mtk_wed_rro_hw_init(struct mtk_wed_device *dev)
 +{
 +	wed_w32(dev, MTK_WED_RROQM_MIOD_CFG,
@@ -723,19 +753,19 @@
 +		FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW,
 +			   MTK_WED_MIOD_ENTRY_CNT >> 2));
 +
-+	wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_desc_phys);
++	wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys);
 +
 +	wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1,
 +		FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT));
 +
-+	wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_desc_phys);
++	wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys);
 +
 +	wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1,
 +		FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT));
 +
 +	wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0);
 +
-+	wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.rro_ring.desc_phys);
++	wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys);
 +
 +	wed_set(dev, MTK_WED_RROQM_RST_IDX,
 +		MTK_WED_RROQM_RST_IDX_MIOD |
@@ -753,12 +783,12 @@
 +{
 +	wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM);
 +
-+	do {
-+		udelay(100);
++	for (;;) {
++		usleep_range(100, 200);
 +
 +		if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM))
 +			break;
-+	} while (1);
++	}
 +
 +	/* configure RX_ROUTE_QM */
 +	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
@@ -771,85 +801,109 @@
 +	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
 +}
 +
-+static void
-+mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_hw_init(struct mtk_wed_device *dev)
  {
- 	int size = dev->buf_ring.size;
- 	int rev_size = MTK_WED_TX_RING_SIZE / 2;
- 	int thr = 1;
+@@ -479,7 +847,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 	dev->init_done = true;
+ 	mtk_wed_set_ext_int(dev, false);
  
--	if (dev->init_done)
--		return;
--
--	dev->init_done = true;
--	mtk_wed_set_ext_int(dev, false);
--
- 	if (dev->ver > MTK_WED_V1) {
--		size = MTK_WED_WDMA_RING_SIZE * 2 + dev->buf_ring.size;
-+		size = MTK_WED_WDMA_RING_SIZE * ARRAY_SIZE(dev->tx_wdma) +
-+		       dev->buf_ring.size;
- 		rev_size = size;
- 		thr = 0;
- 	}
-@@ -609,13 +914,46 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+-	wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
++	wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys);
+ 
+ 	wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
+ 
+@@ -487,7 +855,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 		wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ 			MTK_WED_TX_BM_CTRL_PAUSE |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+-				   dev->buf_ring.size / 128) |
++				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ 				   MTK_WED_TX_RING_SIZE / 256));
+ 		wed_w32(dev, MTK_WED_TX_BM_TKID,
+@@ -503,9 +871,9 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 		wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ 			MTK_WED_TX_BM_CTRL_PAUSE |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+-				   dev->buf_ring.size / 128) |
++				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+-				   dev->buf_ring.size / 128));
++				   dev->tx_buf_ring.size / 128));
+ 		wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
+ 			FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+ 				   dev->wlan.token_start) |
+@@ -518,9 +886,9 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 		wed_w32(dev, MTK_WED_TX_TKID_CTRL,
+ 			MTK_WED_TX_TKID_CTRL_PAUSE |
+ 			FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
+-				   dev->buf_ring.size / 128) |
++				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
+-				   dev->buf_ring.size / 128));
++				   dev->tx_buf_ring.size / 128));
+ 		wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
+ 			FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
+ 			MTK_WED_TX_TKID_DYN_THR_HI);
+@@ -528,27 +896,42 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 
+ 	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
+ 
+-	if (dev->hw->version == 1)
++	if (dev->hw->version == 1) {
+ 		wed_set(dev, MTK_WED_CTRL,
+ 			MTK_WED_CTRL_WED_TX_BM_EN |
+ 			MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+-	else
++	} else {
+ 		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
++		/* rx hw init*/
++		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
++			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
++			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
++
++		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
++
++		mtk_wed_rx_buffer_hw_init(dev);
++		mtk_wed_rro_hw_init(dev);
++		mtk_wed_route_qm_hw_init(dev);
++	}
+ 
+ 	wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
  }
  
  static void
--mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
-+mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
+-mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size)
++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
  {
-+	wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
-+		MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
-+		MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
-+
-+	wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
-+
-+	mtk_wed_rx_bm_hw_init(dev);
-+	mtk_wed_rro_hw_init(dev);
-+	mtk_wed_route_qm_hw_init(dev);
-+}
-+
-+static void
-+mtk_wed_hw_init(struct mtk_wed_device *dev)
-+{
-+	if (dev->init_done)
-+		return;
-+
-+	dev->init_done = true;
-+	mtk_wed_set_ext_int(dev, false);
-+	mtk_wed_tx_hw_init(dev);
-+	if (dev->ver > MTK_WED_V1)
-+		mtk_wed_rx_hw_init(dev);
-+}
-+
-+static void
-+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
-+{
-+	__le32 ctrl;
+ 	void *head = (void *)ring->desc;
  	int i;
  
-+	if (tx)
-+		ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
-+	else
-+		ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST);
-+
  	for (i = 0; i < size; i++) {
+ 		struct mtk_wdma_desc *desc;
++
+ 		desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size);
  		desc->buf0 = 0;
 -		desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
-+		desc->ctrl = ctrl;
++		if (tx)
++			desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
++		else
++			desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST);
  		desc->buf1 = 0;
  		desc->info = 0;
- 		desc += scale;
-@@ -674,7 +1012,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 		if (!desc)
+ 	}
+@@ -604,7 +987,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 		if (!dev->tx_ring[i].desc)
  			continue;
  
--		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver);
-+		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver, true);
+-		mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE);
++		mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE,
++				   true);
  	}
  
  	if (mtk_wed_poll_busy(dev))
-@@ -692,6 +1030,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -622,6 +1006,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
  	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
  
@@ -858,38 +912,21 @@
  	if (busy) {
  		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
  		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
-@@ -729,9 +1069,24 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 
- }
+@@ -661,7 +1047,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  
-+static int
-+mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
-+		   int size)
-+{
-+	ring->desc = dma_alloc_coherent(dev->hw->dev,
-+					size * sizeof(*ring->desc),
-+					&ring->desc_phys, GFP_KERNEL);
-+	if (!ring->desc)
-+		return -ENOMEM;
-+
-+	ring->size = size;
-+	memset(ring->desc, 0, size);
-+	return 0;
-+}
-+
  static int
  mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
--		   int size, int scale)
-+		   int size, int scale, bool tx)
+-		   int size, u32 desc_size)
++		   int size, u32 desc_size, bool tx)
  {
- 	ring->desc = dma_alloc_coherent(dev->hw->dev,
- 					size * sizeof(*ring->desc) * scale,
-@@ -740,17 +1095,18 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
- 		return -ENOMEM;
+ 	ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size,
+ 					&ring->desc_phys, GFP_KERNEL);
+@@ -670,18 +1056,23 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
  
+ 	ring->desc_size = desc_size;
  	ring->size = size;
--	mtk_wed_ring_reset(ring->desc, size, scale);
-+	mtk_wed_ring_reset(ring->desc, size, scale, tx);
+-	mtk_wed_ring_reset(ring, size);
++	mtk_wed_ring_reset(ring, size, tx);
  
  	return 0;
  }
@@ -898,25 +935,36 @@
 -mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
 +mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
  {
- 	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
+ 	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+-	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
++	struct mtk_wed_ring *wdma;
  
--	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, dev->ver))
-+	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+			       dev->ver, true))
+-	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size))
++	if (idx >= ARRAY_SIZE(dev->rx_wdma))
++		return -EINVAL;
++
++	wdma = &dev->rx_wdma[idx];
++	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size,
++			       true))
  		return -ENOMEM;
  
  	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
-@@ -767,22 +1123,143 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -698,6 +1089,62 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
  	return 0;
  }
  
 +static int
 +mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
 +{
-+	struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
++	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
++	struct mtk_wed_ring *wdma;
 +
++	if (idx >= ARRAY_SIZE(dev->tx_wdma))
++		return -EINVAL;
++
++	wdma = &dev->tx_wdma[idx];
 +	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+			       dev->ver, true))
++			       desc_size, true))
 +		return -ENOMEM;
 +
 +	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
@@ -928,136 +976,117 @@
 +	wdma_w32(dev,
 +		 MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
 +
-+	if (idx == 0)  {
-+		wed_w32(dev, MTK_WED_WDMA_RING_TX
-+			+ MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-+		wed_w32(dev, MTK_WED_WDMA_RING_TX
-+			+ MTK_WED_RING_OFS_COUNT, size);
-+		wed_w32(dev, MTK_WED_WDMA_RING_TX
-+			+ MTK_WED_RING_OFS_CPU_IDX, 0);
-+		wed_w32(dev, MTK_WED_WDMA_RING_TX
-+			+ MTK_WED_RING_OFS_DMA_IDX, 0);
++	if (!idx)  {
++		wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE,
++			wdma->desc_phys);
++		wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT,
++			size);
++		wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX,
++			0);
++		wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX,
++			0);
 +	}
 +
 +	return 0;
 +}
 +
-+static int
-+mtk_wed_rro_alloc(struct mtk_wed_device *dev)
++static void
++mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
++			u32 reason, u32 hash)
 +{
-+	struct device_node *np, *node = dev->hw->node;
-+	struct mtk_wed_ring *ring;
-+	struct resource res;
-+	int ret;
-+
-+	np = of_parse_phandle(node, "mediatek,wocpu_dlm", 0);
-+	if (!np)
-+		return -ENODEV;
-+
-+	ret = of_address_to_resource(np, 0, &res);
-+	if (ret)
-+		return ret;
-+
-+	dev->rro.rro_desc = ioremap(res.start, resource_size(&res));
-+
-+	ring = &dev->rro.rro_ring;
-+
-+	dev->rro.miod_desc_phys = res.start;
-+
-+	dev->rro.mcu_view_miod = MTK_WED_WOCPU_VIEW_MIOD_BASE;
-+	dev->rro.fdbk_desc_phys = MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT
-+				  + dev->rro.miod_desc_phys;
-+
-+	if (mtk_wed_rro_ring_alloc(dev, ring, MTK_WED_RRO_QUE_CNT))
-+		return -ENOMEM;
-+
-+	return 0;
-+}
++	struct mtk_eth *eth = dev->hw->eth;
++	struct ethhdr *eh;
 +
-+static int
-+mtk_wed_rro_cfg(struct mtk_wed_device *dev)
-+{
-+	struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+	struct {
-+		struct wo_cmd_ring ring[2];
++	if (!skb)
++		return;
 +
-+		u32 wed;
-+		u8 ver;
-+	} req = {
-+		.ring = {
-+			[0] = {
-+				.q_base = dev->rro.mcu_view_miod,
-+				.cnt = MTK_WED_MIOD_CNT,
-+				.unit = MTK_WED_MIOD_ENTRY_CNT,
-+			},
-+			[1] = {
-+				.q_base = dev->rro.mcu_view_miod +
-+					  MTK_WED_MIOD_ENTRY_CNT *
-+					  MTK_WED_MIOD_CNT,
-+				.cnt = MTK_WED_FB_CMD_CNT,
-+				.unit = 4,
-+			},
-+		},
-+		.wed = 0,
-+	};
++	if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
++		return;
 +
-+	return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
-+				    &req, sizeof(req), true);
++	skb_set_mac_header(skb, 0);
++	eh = eth_hdr(skb);
++	skb->protocol = eh->h_proto;
++	mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash);	
 +}
 +
-+static int
-+mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
-+{
-+	struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+
-+	if (dev->ver == MTK_WED_V1)
-+		return 0;
+ static void
+ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ {
+@@ -720,6 +1167,8 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 
+ 		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
+ 	} else {
++		wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
++					GENMASK(1, 0));
+ 		/* initail tx interrupt trigger */
+ 		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
+ 			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
+@@ -738,6 +1187,16 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
+ 				    dev->wlan.txfree_tbit));
+ 
++		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
++			MTK_WED_WPDMA_INT_CTRL_RX0_EN |
++			MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
++			MTK_WED_WPDMA_INT_CTRL_RX1_EN |
++			MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
++			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
++				   dev->wlan.rx_tbit[0]) |
++			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
++				   dev->wlan.rx_tbit[1]));
 +
-+	return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
-+}
+ 		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
+ 		wed_set(dev, MTK_WED_WDMA_INT_CTRL,
+ 			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
+@@ -775,9 +1234,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ 		wdma_set(dev, MTK_WDMA_GLO_CFG,
+ 			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+ 	} else {
++		int i;
 +
-+static void
-+mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
-+			u32 reason, u32 hash)
-+{
-+	int idx = dev->hw->index;
-+	struct mtk_eth *eth = dev->hw->eth;
-+	struct ethhdr *eh;
+ 		wed_set(dev, MTK_WED_WPDMA_CTRL,
+ 			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
+ 
++		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
++			MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
++			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
 +
-+	if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
-+		if (!skb)
-+			return;
+ 		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+ 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
+ 			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+@@ -785,18 +1250,26 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ 		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+ 			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
+ 			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
 +
-+		skb_set_mac_header(skb, 0);
-+		eh = eth_hdr(skb);
-+		skb->protocol = eh->h_proto;
-+		mtk_ppe_check_skb(eth->ppe[idx], skb, hash);
-+	}
-+}
++		wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++			MTK_WED_WPDMA_RX_D_RX_DRV_EN |
++			FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
++			FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
++				   0x2));
 +
++		for (i = 0; i < MTK_WED_RX_QUEUES; i++)
++			mtk_wed_check_wfdma_rx_fill(dev, i);
+ 	}
+ }
+ 
  static void
  mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
  {
 -	u32 wdma_mask;
--	int i;
-+	int i, ret;
+ 	int i;
  
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- 		if (!dev->tx_wdma[i].desc)
+-	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+-		if (!dev->tx_wdma[i].desc)
 -			mtk_wed_wdma_ring_setup(dev, i, 16);
--
++	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
++		if (!dev->rx_wdma[i].desc)
 +			mtk_wed_wdma_rx_ring_setup(dev, i, 16);
  
- 	mtk_wed_hw_init(dev);
- 
- 	mtk_wed_set_int(dev, irq_mask);
--
--
- 	mtk_wed_set_ext_int(dev, true);
  
- 	if (dev->ver == MTK_WED_V1) {
-@@ -797,8 +1274,20 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- 		val |= BIT(0);
+ 	mtk_wed_hw_init(dev);
+@@ -813,9 +1286,22 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 		val |= BIT(0) | (BIT(1) * !!dev->hw->index);
  		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
  	} else {
 -		mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
@@ -1070,75 +1099,83 @@
 +		wed_r32(dev, MTK_WED_EXT_INT_MASK1);
 +		wed_r32(dev, MTK_WED_EXT_INT_MASK2);
 +
-+		ret = mtk_wed_rro_cfg(dev);
-+		if (ret)
++		if (mtk_wed_rro_cfg(dev))
 +			return;
++
  	}
-+	mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
  
++	mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
++
  	mtk_wed_dma_enable(dev);
  	dev->running = true;
-@@ -809,6 +1298,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	__releases(RCU)
- {
- 	struct mtk_wed_hw *hw;
-+	struct device *device;
- 	u16 ver;
- 	int ret = 0;
- 
-@@ -829,6 +1319,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 		goto out;
+ }
+@@ -844,7 +1330,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	if (!hw) {
+ 		module_put(THIS_MODULE);
+ 		ret = -ENODEV;
+-		goto out;
++		goto unlock;
  	}
  
-+	device = dev->wlan.bus_type == MTK_WED_BUS_PCIE
-+	? &dev->wlan.pci_dev->dev
-+	: &dev->wlan.platform_dev->dev;
-+	dev_info(device, "attaching wed device %d version %d\n",
-+		 hw->index, hw->ver);
-+
- 	dev->hw = hw;
+ 	device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
+@@ -856,26 +1342,40 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  	dev->dev = hw->dev;
  	dev->irq = hw->irq;
-@@ -847,9 +1343,17 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	dev->rev_id = ((dev->ver << 28) | ver << 16);
+ 	dev->wdma_idx = hw->index;
++	dev->version = hw->version;
+ 
+ 	if (hw->eth->dma_dev == hw->eth->dev &&
+ 	    of_dma_is_coherent(hw->eth->dev->of_node))
+ 		mtk_eth_set_dma_device(hw->eth, hw->dev);
  
- 	ret = mtk_wed_buffer_alloc(dev);
+-	ret = mtk_wed_buffer_alloc(dev);
 -	if (ret) {
 -		mtk_wed_detach(dev);
--		goto out;
++	ret = mtk_wed_tx_buffer_alloc(dev);
 +	if (ret)
-+		goto error;
+ 		goto out;
+-	}
 +
-+	if (dev->ver > MTK_WED_V1) {
-+		ret = mtk_wed_rx_bm_alloc(dev);
++	if (mtk_wed_get_rx_capa(dev)) {
++		ret = mtk_wed_rx_buffer_alloc(dev);
 +		if (ret)
-+			goto error;
++			goto out;
 +
 +		ret = mtk_wed_rro_alloc(dev);
 +		if (ret)
-+			goto error;
- 	}
++			goto out;
++ 	}
  
  	mtk_wed_hw_init_early(dev);
-@@ -857,7 +1361,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	if (dev->ver == MTK_WED_V1)
+ 
+-	if (hw->version == 1)
++	if (hw->version == 1) {
  		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
  				   BIT(hw->index), 0);
-+	else
+-	else
++	} else {
+ 		dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
 +		ret = mtk_wed_wo_init(hw);
++	}
  
-+error:
+ out:
 +	if (ret)
 +		mtk_wed_detach(dev);
- out:
++unlock:
  	mutex_unlock(&hw_lock);
  
-@@ -883,10 +1392,10 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ 	return ret;
+@@ -898,13 +1398,14 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ 	 * WDMA RX.
+ 	 */
  
- 	BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
+-	BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
++	if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring)))
++		return -EINVAL;
  
--	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1))
-+	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1, true))
+ 	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
+-			       sizeof(*ring->desc)))
++			       sizeof(*ring->desc), true))
  		return -ENOMEM;
  
 -	if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
@@ -1146,7 +1183,7 @@
  		return -ENOMEM;
  
  	ring->reg_base = MTK_WED_RING_TX(idx);
-@@ -933,6 +1442,35 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -948,6 +1449,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
  	return 0;
  }
  
@@ -1155,10 +1192,11 @@
 +{
 +	struct mtk_wed_ring *ring = &dev->rx_ring[idx];
 +
-+	BUG_ON(idx > ARRAY_SIZE(dev->rx_ring));
-+
++	if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring)))
++		return -EINVAL;
 +
-+	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, 1, false))
++	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
++			       sizeof(*ring->desc), false))
 +		return -ENOMEM;
 +
 +	if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
@@ -1166,6 +1204,7 @@
 +
 +	ring->reg_base = MTK_WED_RING_RX_DATA(idx);
 +	ring->wpdma = regs;
++	ring->flags |= MTK_WED_RING_CONFIGURED;
 +
 +	/* WPDMA ->  WED */
 +	wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
@@ -1182,16 +1221,17 @@
  static u32
  mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
  {
-@@ -1022,6 +1560,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1037,7 +1569,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 	static const struct mtk_wed_ops wed_ops = {
  		.attach = mtk_wed_attach,
  		.tx_ring_setup = mtk_wed_tx_ring_setup,
- 		.txfree_ring_setup = mtk_wed_txfree_ring_setup,
 +		.rx_ring_setup = mtk_wed_rx_ring_setup,
-+		.msg_update = mtk_wed_send_msg,
+ 		.txfree_ring_setup = mtk_wed_txfree_ring_setup,
++		.msg_update = mtk_wed_mcu_msg_update,
  		.start = mtk_wed_start,
  		.stop = mtk_wed_stop,
  		.reset_dma = mtk_wed_reset_dma,
-@@ -1030,6 +1570,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1046,6 +1580,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  		.irq_get = mtk_wed_irq_get,
  		.irq_set_mask = mtk_wed_irq_set_mask,
  		.detach = mtk_wed_detach,
@@ -1199,24 +1239,8 @@
  	};
  	struct device_node *eth_np = eth->dev->of_node;
  	struct platform_device *pdev;
-@@ -1069,6 +1610,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 	hw->wdma_phy = wdma_phy;
- 	hw->index = index;
- 	hw->irq = irq;
-+	hw->ver = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
- 
- 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- 		hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
-@@ -1085,6 +1627,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 			regmap_write(hw->mirror, 0, 0);
- 			regmap_write(hw->mirror, 4, 0);
- 		}
-+		hw->ver = MTK_WED_V1;
- 	}
- 
- 	mtk_wed_hw_add_debugfs(hw);
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 9b17b74..8ef5253 100644
+index c9a20e4..1bfd96f 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.h
 @@ -13,6 +13,7 @@
@@ -1236,29 +1260,22 @@
 +#define MTK_WED_RRO_QUE_CNT		8192
 +#define MTK_WED_MIOD_ENTRY_CNT		128
 +
-+#define MODULE_ID_WO		1
++#define MTK_WED_MODULE_ID_WO		1
  
  struct mtk_eth;
 +struct mtk_wed_wo;
  
  struct mtk_wed_hw {
  	struct device_node *node;
-@@ -34,12 +42,14 @@ struct mtk_wed_hw {
+@@ -35,6 +43,7 @@ struct mtk_wed_hw {
  	struct regmap *mirror;
  	struct dentry *debugfs_dir;
  	struct mtk_wed_device *wed_dev;
 +	struct mtk_wed_wo *wed_wo;
  	u32 debugfs_reg;
  	u32 num_flows;
- 	u32 wdma_phy;
- 	char dirname[5];
- 	int irq;
- 	int index;
-+	u32 ver;
- };
- 
- struct mtk_wdma_info {
-@@ -66,6 +76,18 @@ wed_r32(struct mtk_wed_device *dev, u32 reg)
+ 	u8 version;
+@@ -67,6 +76,18 @@ wed_r32(struct mtk_wed_device *dev, u32 reg)
  	return val;
  }
  
@@ -1277,8 +1294,8 @@
  static inline void
  wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
  {
-@@ -114,6 +136,23 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
- 	writel(val, dev->txfree_ring.wpdma + reg);
+@@ -97,6 +118,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val)
+ 	writel(val, dev->tx_ring[ring].wpdma + reg);
  }
  
 +static inline u32
@@ -1298,10 +1315,11 @@
 +
 +	writel(val, dev->rx_ring[ring].wpdma + reg);
 +}
- void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 		    void __iomem *wdma, u32 wdma_phy, int index);
- void mtk_wed_exit(void);
-@@ -146,4 +185,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
++
+ static inline u32
+ wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg)
+ {
+@@ -149,4 +188,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
  }
  #endif
  
@@ -1509,7 +1527,7 @@
 +
 +#endif
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-index f420f18..4a9e684 100644
+index f420f18..7d8be99 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
 @@ -2,6 +2,7 @@
@@ -1645,16 +1663,16 @@
  	debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
  	debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
 +	debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
-+	if (hw->ver != MTK_WED_V1) {
++	if (hw->version != 1) {
 +		wed_wo_mcu_debugfs(hw, dir);
 +	}
  }
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
 new file mode 100644
-index 0000000..96e30a3
+index 0000000..be63406
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -0,0 +1,590 @@
+@@ -0,0 +1,604 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +
 +#include <linux/skbuff.h>
@@ -1743,6 +1761,20 @@
 +	return ret;
 +}
 +
++int
++mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len)
++{
++	struct mtk_wed_wo *wo = dev->hw->wed_wo;
++
++	if (dev->hw->version == 1)
++		return 0;
++
++	if (WARN_ON(!wo))
++		return -ENODEV;
++
++	return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, true);
++}
++
 +void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo,
 +			struct sk_buff *skb)
 +{
@@ -1804,7 +1836,7 @@
 +	req.arg0 = (u32)exp->phys;
 +	req.arg1 = (u32)exp->log_size;
 +
-+	return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_EXCEPTION_INIT,
++	return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_EXCEPTION_INIT,
 +				    &req, sizeof(req), false);
 +
 +free:
@@ -2030,7 +2062,7 @@
 +	hdr->length = cpu_to_le16(skb->len);
 +	hdr->uni_id = seq;
 +
-+	if (to_id == MODULE_ID_WO)
++	if (to_id == MTK_WED_MODULE_ID_WO)
 +		hdr->flag |= WARP_CMD_FLAG_FROM_TO_WO;
 +
 +	if (wait_resp && wait_seq)
@@ -2225,7 +2257,7 @@
 +		return count;
 +	}
 +
-+	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, (void *)msgbuf, sizeof(struct wo_cmd_query), wait);
++	mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, cmd_id, (void *)msgbuf, sizeof(struct wo_cmd_query), wait);
 +
 +	return count;
 +
@@ -2247,7 +2279,7 @@
 +
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
 new file mode 100644
-index 0000000..19e1199
+index 0000000..dbb17ae
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
 @@ -0,0 +1,97 @@
@@ -2349,19 +2381,18 @@
 +
 +#endif
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 14e0e21..31871f7 100644
+index e797e9d..a79305f 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -4,6 +4,8 @@
+@@ -4,6 +4,7 @@
  #ifndef __MTK_WED_REGS_H
  #define __MTK_WED_REGS_H
  
 +#define MTK_WFDMA_DESC_CTRL_TO_HOST		BIT(8)
-+
- #if defined(CONFIG_MEDIATEK_NETSYS_V2)
- #define MTK_WDMA_DESC_CTRL_LEN1			GENMASK(13, 0)
- #define MTK_WDMA_DESC_CTRL_LAST_SEG1		BIT(14)
-@@ -16,6 +18,7 @@
+ #define MTK_WDMA_DESC_CTRL_LEN1			GENMASK(14, 0)
+ #define MTK_WDMA_DESC_CTRL_LEN1_V2		GENMASK(13, 0)
+ #define MTK_WDMA_DESC_CTRL_LAST_SEG1		BIT(15)
+@@ -11,6 +12,7 @@
  #define MTK_WDMA_DESC_CTRL_LEN0			GENMASK(29, 16)
  #define MTK_WDMA_DESC_CTRL_LAST_SEG0		BIT(30)
  #define MTK_WDMA_DESC_CTRL_DMA_DONE		BIT(31)
@@ -2369,7 +2400,7 @@
  
  struct mtk_wdma_desc {
  	__le32 buf0;
-@@ -42,6 +45,8 @@ struct mtk_wdma_desc {
+@@ -37,6 +39,8 @@ struct mtk_wdma_desc {
  #define MTK_WED_RESET_WED_TX_DMA			BIT(12)
  #define MTK_WED_RESET_WDMA_RX_DRV			BIT(17)
  #define MTK_WED_RESET_WDMA_INT_AGENT			BIT(19)
@@ -2378,7 +2409,7 @@
  #define MTK_WED_RESET_WED				BIT(31)
  
  #define MTK_WED_CTRL					0x00c
-@@ -53,8 +58,12 @@ struct mtk_wdma_desc {
+@@ -48,8 +52,12 @@ struct mtk_wdma_desc {
  #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
  #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
  #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY		BIT(11)
@@ -2393,7 +2424,7 @@
  #define MTK_WED_CTRL_FINAL_DIDX_READ			BIT(24)
  #define MTK_WED_CTRL_ETH_DMAD_FMT			BIT(25)
  #define MTK_WED_CTRL_MIB_READ_CLEAR			BIT(28)
-@@ -69,8 +78,8 @@ struct mtk_wdma_desc {
+@@ -64,8 +72,8 @@ struct mtk_wdma_desc {
  #define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH		BIT(10)
  #define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH		BIT(11)
  #endif
@@ -2404,7 +2435,7 @@
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR	BIT(16)
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR	BIT(17)
  #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT		BIT(18)
-@@ -87,8 +96,8 @@ struct mtk_wdma_desc {
+@@ -82,8 +90,8 @@ struct mtk_wdma_desc {
  #define MTK_WED_EXT_INT_STATUS_ERROR_MASK		(MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
  							 MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
  							 MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
@@ -2415,7 +2446,7 @@
  							 MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
  							 MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
  							 MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
-@@ -96,6 +105,8 @@ struct mtk_wdma_desc {
+@@ -91,6 +99,8 @@ struct mtk_wdma_desc {
  							 MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
  
  #define MTK_WED_EXT_INT_MASK				0x028
@@ -2424,7 +2455,7 @@
  
  #define MTK_WED_STATUS					0x060
  #define MTK_WED_STATUS_TX				GENMASK(15, 8)
-@@ -183,6 +194,9 @@ struct mtk_wdma_desc {
+@@ -172,6 +182,9 @@ struct mtk_wdma_desc {
  
  #define MTK_WED_RING_RX(_n)				(0x400 + (_n) * 0x10)
  
@@ -2434,7 +2465,7 @@
  #define MTK_WED_WPDMA_INT_TRIGGER			0x504
  #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE		BIT(1)
  #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE		GENMASK(5, 4)
-@@ -239,13 +253,19 @@ struct mtk_wdma_desc {
+@@ -228,13 +241,19 @@ struct mtk_wdma_desc {
  
  #define MTK_WED_WPDMA_INT_CTRL_TX			0x530
  #define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN 		BIT(0)
@@ -2455,7 +2486,7 @@
  
  #define MTK_WED_WPDMA_INT_CTRL_TX_FREE			0x538
  #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN		BIT(0)
-@@ -270,13 +290,40 @@ struct mtk_wdma_desc {
+@@ -259,13 +278,40 @@ struct mtk_wdma_desc {
  #define MTK_WED_WPDMA_TX_MIB(_n)			(0x5a0 + (_n) * 4)
  #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n)		(0x5d0 + (_n) * 4)
  
@@ -2496,7 +2527,7 @@
  #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN			BIT(2)
  #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY		BIT(3)
  #define MTK_WED_WDMA_GLO_CFG_BT_SIZE			GENMASK(5, 4)
-@@ -320,6 +367,20 @@ struct mtk_wdma_desc {
+@@ -309,6 +355,20 @@ struct mtk_wdma_desc {
  #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n)			(0xae8 + (_n) * 4)
  #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n)		(0xaf0 + (_n) * 4)
  
@@ -2517,7 +2548,7 @@
  #define MTK_WED_RING_OFS_BASE				0x00
  #define MTK_WED_RING_OFS_COUNT				0x04
  #define MTK_WED_RING_OFS_CPU_IDX			0x08
-@@ -330,12 +391,13 @@ struct mtk_wdma_desc {
+@@ -319,12 +379,13 @@ struct mtk_wdma_desc {
  
  #define MTK_WDMA_GLO_CFG				0x204
  #define MTK_WDMA_GLO_CFG_TX_DMA_EN			BIT(0)
@@ -2532,7 +2563,7 @@
  #define MTK_WDMA_RESET_IDX				0x208
  #define MTK_WDMA_RESET_IDX_TX				GENMASK(3, 0)
  #define MTK_WDMA_RESET_IDX_RX				GENMASK(17, 16)
-@@ -359,4 +421,70 @@ struct mtk_wdma_desc {
+@@ -348,4 +409,70 @@ struct mtk_wdma_desc {
  /* DMA channel mapping */
  #define HIFSYS_DMA_AG_MAP				0x008
  
@@ -3175,10 +3206,10 @@
 +}
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
 new file mode 100644
-index 0000000..548b38e
+index 0000000..b24fef3
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-@@ -0,0 +1,324 @@
+@@ -0,0 +1,325 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
 +
@@ -3499,23 +3530,31 @@
 +	return val;
 +}
 +
++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len);
 +int mtk_wed_wo_init(struct mtk_wed_hw *hw);
 +void mtk_wed_wo_exit(struct mtk_wed_hw *hw);
 +#endif
 +
 diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index e914cb4..e8fca31 100644
+index 00036f9..658f392 100644
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -6,7 +6,39 @@
- #include <linux/regmap.h>
+@@ -7,26 +7,73 @@
  #include <linux/pci.h>
  
-+#define WED_WO_STA_REC			0x6
-+
  #define MTK_WED_TX_QUEUES		2
 +#define MTK_WED_RX_QUEUES		2
-+
+ 
+-enum {
+-	MTK_BUS_TYPE_PCIE,
+-	MTK_BUS_TYPE_AXI,
+-	MTK_BUS_TYPE_MAX
+-};
++#define WED_WO_STA_REC			0x6
+ 
+ struct mtk_wed_hw;
+ struct mtk_wdma_desc;
+ 
 +enum mtk_wed_wo_cmd {
 +	MTK_WED_WO_CMD_WED_CFG,
 +	MTK_WED_WO_CMD_WED_RX_STAT,
@@ -3544,45 +3583,29 @@
 +	MTK_WED_WO_CMD_CCIF_RING_DUMP,
 +	MTK_WED_WO_CMD_WED_END
 +};
- 
- enum {
- 	MTK_NO_WED,
-@@ -15,10 +47,9 @@ enum {
- 	MTK_WED_VMAX
- };
- 
--enum {
--	MTK_BUS_TYPE_PCIE,
--	MTK_BUS_TYPE_AXI,
--	MTK_BUS_TYPE_MAX
-+enum mtk_wed_bus_tye {
-+	MTK_WED_BUS_PCIE,
-+	MTK_WED_BUS_AXI,
- };
- 
- struct mtk_wed_hw;
-@@ -33,6 +64,33 @@ struct mtk_wed_ring {
- 	void __iomem *wpdma;
- };
- 
++
 +struct mtk_rxbm_desc {
 +	__le32 buf0;
 +	__le32 token;
 +} __packed __aligned(4);
 +
-+struct dma_buf {
-+	int size;
-+	void **pages;
-+	struct mtk_wdma_desc *desc;
-+	dma_addr_t desc_phys;
-+};
-+
-+struct dma_entry {
-+	int size;
-+	struct mtk_rxbm_desc *desc;
-+	dma_addr_t desc_phys;
++enum mtk_wed_bus_tye{
++	MTK_WED_BUS_PCIE,
++	MTK_WED_BUS_AXI,
 +};
 +
++#define MTK_WED_RING_CONFIGURED		BIT(0)
+ struct mtk_wed_ring {
+ 	struct mtk_wdma_desc *desc;
+ 	dma_addr_t desc_phys;
+ 	u32 desc_size;
+ 	int size;
++	u32 flags;
+ 
+ 	u32 reg_base;
+ 	void __iomem *wpdma;
+ };
+ 
 +struct mtk_wed_wo_rx_stats {
 +	__le16 wlan_idx;
 +	__le16 tid;
@@ -3595,42 +3618,49 @@
  struct mtk_wed_device {
  #ifdef CONFIG_NET_MEDIATEK_SOC_WED
  	const struct mtk_wed_ops *ops;
-@@ -47,37 +105,64 @@ struct mtk_wed_device {
+@@ -35,18 +82,37 @@ struct mtk_wed_device {
+ 	bool init_done, running;
+ 	int wdma_idx;
+ 	int irq;
++	u8 version;
++
++	/* used by wlan driver */
+ 	u32 rev_id;
+ 
  	struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
++	struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
  	struct mtk_wed_ring txfree_ring;
  	struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES];
-+	struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
 +	struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
-+
-+	struct dma_buf buf_ring;
  
  	struct {
  		int size;
--		void **pages;
--		struct mtk_wdma_desc *desc;
-+		struct page_frag_cache rx_page;
-+		struct mtk_rxbm_desc *desc;
+ 		void **pages;
+ 		struct mtk_wdma_desc *desc;
  		dma_addr_t desc_phys;
 -	} buf_ring;
-+	} rx_buf_ring;
++	} tx_buf_ring;
++
++ 	struct {
++ 		int size;
++ 		struct page_frag_cache rx_page;
++		struct mtk_rxbm_desc *desc;
++ 		dma_addr_t desc_phys;
++ 	} rx_buf_ring;
 +
 +	struct {
-+		struct mtk_wed_ring rro_ring;
++		struct mtk_wed_ring ring;
 +		void __iomem *rro_desc;
-+		dma_addr_t miod_desc_phys;
-+		dma_addr_t fdbk_desc_phys;
-+		u32 mcu_view_miod;
++		dma_addr_t miod_phys;
++		dma_addr_t fdbk_phys;
 +	} rro;
  
  	/* filled by driver: */
  	struct {
--		struct pci_dev *pci_dev;
-+		union {
-+			struct platform_device *platform_dev;
-+			struct pci_dev *pci_dev;
-+		};
+@@ -56,24 +122,35 @@ struct mtk_wed_device {
+ 		};
+ 		enum mtk_wed_bus_tye bus_type;
  		void __iomem *base;
- 		u32 bus_type;
 +		u32 phy_base;
  
  		u32 wpdma_phys;
@@ -3656,35 +3686,30 @@
  		u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
  		int (*offload_enable)(struct mtk_wed_device *wed);
  		void (*offload_disable)(struct mtk_wed_device *wed);
-+		u32 (*init_rx_buf)(struct mtk_wed_device *wed,
-+				   int pkt_num);
++		u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size);
 +		void (*release_rx_buf)(struct mtk_wed_device *wed);
 +		void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
 +					   struct mtk_wed_wo_rx_stats *stats);
  	} wlan;
  #endif
  };
-@@ -88,6 +173,10 @@ struct mtk_wed_ops {
+@@ -82,9 +159,15 @@ struct mtk_wed_ops {
+ 	int (*attach)(struct mtk_wed_device *dev);
+ 	int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
  			     void __iomem *regs);
++	int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++			     void __iomem *regs);
  	int (*txfree_ring_setup)(struct mtk_wed_device *dev,
  				 void __iomem *regs);
-+	int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+				 void __iomem *regs);
 +	int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
 +			  void *data, int len);
  	void (*detach)(struct mtk_wed_device *dev);
- 
- 	void (*stop)(struct mtk_wed_device *dev);
-@@ -99,6 +188,8 @@ struct mtk_wed_ops {
- 
- 	u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
- 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
 +	void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
 +			  u32 reason, u32 hash);
- };
  
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -123,6 +214,16 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
+ 	void (*stop)(struct mtk_wed_device *dev);
+ 	void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
+@@ -119,6 +202,16 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
  	return ret;
  }
  
@@ -3692,7 +3717,7 @@
 +mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
 +{
 +#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+	return dev->ver != 1;
++	return dev->version != 1;
 +#else
 +	return false;
 +#endif
@@ -3701,37 +3726,26 @@
  #ifdef CONFIG_NET_MEDIATEK_SOC_WED
  #define mtk_wed_device_active(_dev) !!(_dev)->ops
  #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
-@@ -131,6 +232,10 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
- 	(_dev)->ops->tx_ring_setup(_dev, _ring, _regs)
- #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
- 	(_dev)->ops->txfree_ring_setup(_dev, _regs)
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
-+	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
-+	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
- #define mtk_wed_device_reg_read(_dev, _reg) \
- 	(_dev)->ops->reg_read(_dev, _reg)
- #define mtk_wed_device_reg_write(_dev, _reg, _val) \
-@@ -139,6 +244,8 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
+@@ -135,6 +228,12 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
  	(_dev)->ops->irq_get(_dev, _mask)
  #define mtk_wed_device_irq_set_mask(_dev, _mask) \
  	(_dev)->ops->irq_set_mask(_dev, _mask)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
++	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
 +#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
 +	(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
++	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
  #else
  static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
  {
-@@ -148,10 +255,13 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_start(_dev, _mask) do {} while (0)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV
- #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
- #define mtk_wed_device_reg_read(_dev, _reg) 0
+@@ -148,6 +247,9 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
  #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
  #define mtk_wed_device_irq_get(_dev, _mask) 0
  #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
 +#define mtk_wed_device_ppe_check(_dev, _hash)  do {} while (0)
++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
  #endif
  
  #endif
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3009-add-wed-ser-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3009-add-wed-ser-support.patch
index c53746f..28417c1 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3009-add-wed-ser-support.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3009-add-wed-ser-support.patch
@@ -1,21 +1,21 @@
-From de9cc10d4e2d5aad4801dc92fb37c42478a4ab68 Mon Sep 17 00:00:00 2001
+From d62ace95491fa4569c9ca9bca0b49b4995194a45 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:05:45 +0800
-Subject: [PATCH 10/22] add-wed-ser-support
+Subject: [PATCH 09/24] add-wed-ser-support
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c  |   8 +
- drivers/net/ethernet/mediatek/mtk_wed.c      | 361 ++++++++++++++-----
- drivers/net/ethernet/mediatek/mtk_wed.h      |  11 +
- drivers/net/ethernet/mediatek/mtk_wed_regs.h |  12 +
- include/linux/soc/mediatek/mtk_wed.h         |  27 +-
- 5 files changed, 320 insertions(+), 99 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed.c      | 391 ++++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed.h      |  10 +
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h |   9 +
+ include/linux/soc/mediatek/mtk_wed.h         |  25 +-
+ 5 files changed, 342 insertions(+), 101 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 2cab49a..c1399c5 100644
+index 268c9e7..a24b223 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -4158,6 +4158,9 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4619,6 +4619,9 @@ static void mtk_pending_work(struct work_struct *work)
  	for (i = 0; i < MTK_MAC_COUNT; i++) {
  		if (!eth->netdev[i])
  			continue;
@@ -25,7 +25,7 @@
  		if (mtk_reset_flag == MTK_FE_STOP_TRAFFIC) {
  			pr_info("send MTK_FE_STOP_TRAFFIC event\n");
  			call_netdevice_notifiers(MTK_FE_STOP_TRAFFIC,
-@@ -4183,6 +4186,7 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4644,6 +4647,7 @@ static void mtk_pending_work(struct work_struct *work)
  			pr_warn("wait for MTK_FE_START_RESET\n");
  		}
  		rtnl_lock();
@@ -33,7 +33,7 @@
  		break;
  	}
  
-@@ -4221,6 +4225,9 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4682,6 +4686,9 @@ static void mtk_pending_work(struct work_struct *work)
  	for (i = 0; i < MTK_MAC_COUNT; i++) {
  		if (!eth->netdev[i])
  			continue;
@@ -43,7 +43,7 @@
  		if (mtk_reset_flag == MTK_FE_STOP_TRAFFIC) {
  			pr_info("send MTK_FE_START_TRAFFIC event\n");
  			call_netdevice_notifiers(MTK_FE_START_TRAFFIC,
-@@ -4230,6 +4237,7 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4691,6 +4698,7 @@ static void mtk_pending_work(struct work_struct *work)
  			call_netdevice_notifiers(MTK_FE_RESET_DONE,
  				eth->netdev[i]);
  		}
@@ -52,7 +52,7 @@
  			eth->netdev[i]);
  		break;
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 4b2f1a2..ae31412 100644
+index ad9f3d5..5dd1182 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
 @@ -13,8 +13,10 @@
@@ -66,60 +66,52 @@
  #include "mtk_wed_regs.h"
  #include "mtk_wed.h"
  #include "mtk_ppe.h"
-@@ -71,23 +73,27 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
- 	return wdma_r32(dev, MTK_WDMA_GLO_CFG);
- }
- 
--static void
-+static int
- mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- {
- 	u32 status;
- 	u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
--	int i;
-+	int busy, i;
+@@ -80,10 +82,13 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
  
  	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
--	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
--			       !(status & mask), 0, 1000))
--		WARN_ON_ONCE(1);
-+	busy = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-+			       !(status & mask), 0, 10000);
-+
+ 	ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
+-				 !(status & mask), 0, 1000)
++				 !(status & mask), 0, 10000);
+ 	if (ret)
+ 		dev_err(dev->hw->dev, "rx reset failed \n");
+ 
 +	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
 +	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
- 
- 	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
- 		if (!dev->rx_wdma[i].desc) {
- 			wdma_w32(dev, MTK_WDMA_RING_RX(i) +
- 				 MTK_WED_RING_OFS_CPU_IDX, 0);
++
+ 	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
+ 		if (!dev->rx_wdma[i].desc)
+ 			continue;
+@@ -91,6 +96,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ 		wdma_w32(dev,
+ 			 MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
  	}
 +
-+	return busy;
++	return ret;
  }
  
  static void
-@@ -99,14 +105,14 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+@@ -101,16 +108,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
  
  	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
  	if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
 -			       !(status & mask), 0, 1000))
 +			       !(status & mask), 0, 10000))
- 		WARN_ON_ONCE(1);
+ 		dev_err(dev->hw->dev, "tx reset failed \n");
  
+-	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) {
+-		if (!dev->tx_wdma[i].desc)
+-			continue;
 +	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
 +	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
--		if (!dev->tx_wdma[i].desc) {
--			wdma_w32(dev, MTK_WDMA_RING_TX(i) +
--				 MTK_WED_RING_OFS_CPU_IDX, 0);
+ 
++	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+ 		wdma_w32(dev,
+ 			 MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
 -	}
-+		wdma_w32(dev, MTK_WDMA_RING_TX(i) +
-+			 MTK_WED_RING_OFS_CPU_IDX, 0);
  }
  
- static u32
-@@ -172,6 +178,51 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
+ static void
+@@ -176,6 +182,59 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
  	iounmap((void *)reg);
  }
  
@@ -131,9 +123,13 @@
 +
 +	for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
 +		struct mtk_wed_hw *hw = hw_list[i];
-+		struct mtk_wed_device *dev = hw->wed_dev;
++		struct mtk_wed_device *dev;
 +		int err;
 +
++		if (!hw)
++			break;
++
++		dev = hw->wed_dev;
 +		if (!dev || !dev->wlan.reset)
 +			continue;
 +
@@ -156,8 +152,12 @@
 +
 +	for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
 +		struct mtk_wed_hw *hw = hw_list[i];
-+		struct mtk_wed_device *dev = hw->wed_dev;
++		struct mtk_wed_device *dev;
++
++		if (!hw)
++			break;
 +
++		dev = hw->wed_dev;
 +		if (!dev || !dev->wlan.reset_complete)
 +			continue;
 +
@@ -171,123 +171,134 @@
  static struct mtk_wed_hw *
  mtk_wed_assign(struct mtk_wed_device *dev)
  {
-@@ -505,8 +556,8 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
- 		wifi_w32(dev, dev->wlan.wpdma_rx_glo -
- 			 dev->wlan.phy_base, val);
- 	} else {
+@@ -473,8 +532,8 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
+ 	}
+ 
+ 	if (i == 3) {
 -		dev_err(dev->hw->dev, "mtk_wed%d: rx dma enable failed!\n",
 -			       dev->hw->index);
 +		dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
 +			       dev->hw->index, idx);
+ 		return;
  	}
- }
- 
-@@ -557,7 +608,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- 			FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
- 				   0x2));
  
--		for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++)
-+		for (idx = 0; idx < dev->hw->ring_num; idx++)
- 			mtk_wed_check_wfdma_rx_fill(dev, idx);
- 	}
- }
-@@ -594,36 +645,45 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
- 		wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
- 			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
- 	}
-+
-+	mtk_wed_set_512_support(dev, false);
- }
- 
+@@ -522,16 +581,8 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
  static void
  mtk_wed_stop(struct mtk_wed_device *dev)
  {
 -	mtk_wed_dma_disable(dev);
--	mtk_wed_set_512_support(dev, false);
 -
- 	if (dev->ver > MTK_WED_V1) {
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
- 		wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
- 	}
  	mtk_wed_set_ext_int(dev, false);
  
-+	wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
-+	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
-+	wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-+	wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
-+	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
-+}
-+
-+static void
+-	wed_clr(dev, MTK_WED_CTRL,
+-		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
+-		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
+-		MTK_WED_CTRL_WED_TX_BM_EN |
+-		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+-
+ 	wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
+ 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
+ 	wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
+@@ -543,39 +594,49 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+ 
+ 	wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
+ 	wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
+-	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
+-
+ }
+ 
+ static void
+-mtk_wed_detach(struct mtk_wed_device *dev)
 +mtk_wed_deinit(struct mtk_wed_device *dev)
-+{
+ {
+-	struct device_node *wlan_node;
+-	struct mtk_wed_hw *hw = dev->hw;
 +	mtk_wed_stop(dev);
 +	mtk_wed_dma_disable(dev);
-+
- 	wed_clr(dev, MTK_WED_CTRL,
- 		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
- 		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
- 		MTK_WED_CTRL_WED_TX_BM_EN |
- 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
  
--	if (dev->ver > MTK_WED_V1) {
--		wed_clr(dev, MTK_WED_CTRL,
--			MTK_WED_CTRL_WED_RX_BM_EN);
--	}
-+	if (dev->hw->ver == 1)
+-	mutex_lock(&hw_lock);
++	wed_clr(dev, MTK_WED_CTRL,
++		MTK_WED_CTRL_WDMA_INT_AGENT_EN |
++		MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
++		MTK_WED_CTRL_WED_TX_BM_EN |
++		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+ 
+-	mtk_wed_stop(dev);
++	if (dev->hw->version == 1)
 +		return;
  
--	wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
--	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
--	wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
--	wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
--	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+-	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
+-	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
 +	wed_clr(dev, MTK_WED_CTRL,
 +		MTK_WED_CTRL_RX_ROUTE_QM_EN |
 +		MTK_WED_CTRL_WED_RX_BM_EN |
 +		MTK_WED_CTRL_RX_RRO_QM_EN);
- }
- 
- static void
-@@ -634,16 +694,13 @@ mtk_wed_detach(struct mtk_wed_device *dev)
++}
  
- 	mutex_lock(&hw_lock);
+-	mtk_wed_reset(dev, MTK_WED_RESET_WED);
++static void
++__mtk_wed_detach(struct mtk_wed_device *dev)
++{
++	struct device_node *wlan_node;
++	struct mtk_wed_hw *hw = dev->hw;
  
--	mtk_wed_stop(dev);
+-	if (mtk_wed_get_rx_capa(dev)) {
+-		wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
+-		wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+-		wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+-	}
 +	mtk_wed_deinit(dev);
  
--	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
--	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
 +	mtk_wdma_rx_reset(dev);
- 
- 	mtk_wed_reset(dev, MTK_WED_RESET_WED);
- 
--	wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
--	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
--	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-+	mtk_wdma_tx_reset(dev);
- 
- 	mtk_wed_free_buffer(dev);
++	mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ 	mtk_wed_free_tx_buffer(dev);
  	mtk_wed_free_tx_rings(dev);
-@@ -653,8 +710,6 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- 		mtk_wed_wo_exit(hw);
+ 
+ 	if (mtk_wed_get_rx_capa(dev)) {
+-		mtk_wed_wo_reset(dev);
++		if(hw->wed_wo)
++			mtk_wed_wo_reset(dev);
+ 		mtk_wed_free_rx_rings(dev);
+-		mtk_wed_wo_exit(hw);
+-		mtk_wdma_rx_reset(dev);
++		if(hw->wed_wo)
++			mtk_wed_wo_exit(hw);
++		mtk_wdma_tx_reset(dev);
  	}
  
--	mtk_wdma_rx_reset(dev);
--
  	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
- 		wlan_node = dev->wlan.pci_dev->dev.of_node;
- 		if (of_dma_is_coherent(wlan_node))
-@@ -748,7 +803,7 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -593,6 +654,13 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ 	module_put(THIS_MODULE);
+ 
+ 	hw->wed_dev = NULL;
++}
++
++static void
++mtk_wed_detach(struct mtk_wed_device *dev)
++{
++	mutex_lock(&hw_lock);
++	__mtk_wed_detach(dev);
+ 	mutex_unlock(&hw_lock);
+ }
+ 
+@@ -665,7 +733,7 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
  {
  	u32 mask, set;
  
 -	mtk_wed_stop(dev);
 +	mtk_wed_deinit(dev);
  	mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ 	mtk_wed_set_wpdma(dev);
+ 
+@@ -715,7 +783,6 @@ mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+ 
+ 	ring->desc_size = sizeof(*ring->desc);
+ 	ring->size = size;
+-	memset(ring->desc, 0, size);
  
- 	if (dev->ver > MTK_WED_V1)
-@@ -961,44 +1016,127 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
+ 	return 0;
+ }
+@@ -938,44 +1005,140 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
  }
  
  static u32
@@ -314,7 +325,7 @@
 -
 -	if (wed_r32(dev, MTK_WED_CTRL) &
 -	    (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY))
-+ 	if (wed_r32(dev, reg) & mask)
++	if (wed_r32(dev, reg) & mask)
  		return true;
  
  	return false;
@@ -332,23 +343,26 @@
  	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
 -				 timeout, false, dev);
 +				 timeout, false, dev, reg, mask);
- }
- 
-+static void
++}
++
++static int
 +mtk_wed_rx_reset(struct mtk_wed_device *dev)
 +{
 +	struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+	u8 state = WO_STATE_SER_RESET;
-+	bool busy = false;
-+	int i;
++	u8 val = WO_STATE_SER_RESET;
++	int i, ret;
 +
-+	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+			     &state, sizeof(state), true);
++	mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++			     MTK_WED_WO_CMD_CHANGE_STATE, &val,
++			     sizeof(val), true);
++
++	if (ret)
++		return ret;
 +
 +	wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
-+	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
-+				 MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
-+	if (busy) {
++	ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++				MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
++	if (ret) {
 +		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
 +		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
 +	} else {
@@ -368,9 +382,9 @@
 +
 +	/* reset rro qm */
 +	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN);
-+	busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+				 MTK_WED_CTRL_RX_RRO_QM_BUSY);
-+	if (busy) {
++	ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++				MTK_WED_CTRL_RX_RRO_QM_BUSY);
++	if (ret) {
 +		mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM);
 +	} else {
 +		wed_set(dev, MTK_WED_RROQM_RST_IDX,
@@ -381,9 +395,9 @@
 +
 +	/* reset route qm */
 +	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
-+	busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+				 MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
-+	if (busy) {
++	ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++				MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
++	if (ret) {
 +		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
 +	} else {
 +		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
@@ -400,66 +414,73 @@
 +	mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
 +
 +	/* reset wed rx dma */
-+	busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
-+				 MTK_WED_GLO_CFG_RX_DMA_BUSY);
++	ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
++				MTK_WED_GLO_CFG_RX_DMA_BUSY);
 +	wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN);
-+	if (busy) {
++	if (ret) {
 +		mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA);
 +	} else {
-+		wed_set(dev, MTK_WED_RESET_IDX,
-+			MTK_WED_RESET_IDX_RX);
++		struct mtk_eth *eth = dev->hw->eth;
++
++		if(MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++			wed_set(dev, MTK_WED_RESET_IDX,
++				MTK_WED_RESET_IDX_RX_V2);
++		else
++			wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX);
 +		wed_w32(dev, MTK_WED_RESET_IDX, 0);
 +	}
 +
 +	/* reset rx bm */
 +	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
 +	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+			   MTK_WED_CTRL_WED_RX_BM_BUSY);
++			  MTK_WED_CTRL_WED_RX_BM_BUSY);
 +	mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
 +
 +	/* wo change to enable state */
-+	state = WO_STATE_ENABLE;
-+	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+			     &state, sizeof(state), true);
++	val = WO_STATE_ENABLE;
++	ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++				   MTK_WED_WO_CMD_CHANGE_STATE, &val,
++				   sizeof(val), true);
++
++	if (ret)
++		return ret;
 +
 +	/* wed_rx_ring_reset */
 +	for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) {
-+		struct mtk_wdma_desc *desc = dev->rx_ring[i].desc;
-+
-+		if (!desc)
++		if (!dev->rx_ring[i].desc)
 +			continue;
 +
-+		mtk_wed_ring_reset(desc, MTK_WED_RX_RING_SIZE, 1, false);
++		mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE,
++				   false);
 +	}
 +
-+	mtk_wed_free_rx_bm(dev);
-+}
++	mtk_wed_free_rx_buffer(dev);
 +
++	return 0;
+ }
+ 
 +
  static void
  mtk_wed_reset_dma(struct mtk_wed_device *dev)
  {
-@@ -1012,25 +1150,28 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 		if (!desc)
- 			continue;
- 
--		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver, true);
-+		mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, 1, true);
+@@ -991,22 +1154,25 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 				   true);
  	}
  
 -	if (mtk_wed_poll_busy(dev))
 -		busy = mtk_wed_check_busy(dev);
 +	/* 1.Reset WED Tx DMA */
 +	wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN);
-+	busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_BUSY);
++	busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
++				 MTK_WED_GLO_CFG_TX_DMA_BUSY);
  
  	if (busy) {
  		mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA);
  	} else {
- 		wed_w32(dev, MTK_WED_RESET_IDX,
+-		wed_w32(dev, MTK_WED_RESET_IDX,
 -			MTK_WED_RESET_IDX_TX |
 -			MTK_WED_RESET_IDX_RX);
-+			MTK_WED_RESET_IDX_TX);
++		wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX);
  		wed_w32(dev, MTK_WED_RESET_IDX, 0);
  	}
  
@@ -470,138 +491,153 @@
  
 -	mtk_wdma_rx_reset(dev);
 +	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+	busy = !!(busy ||
-+		  mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
-+					 MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
++	if (!busy)
++		busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
++					 MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY);
  
  	if (busy) {
  		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
-@@ -1047,15 +1188,30 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1023,6 +1189,9 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  			MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE);
  	}
  
 +	/* 3. Reset WED WPDMA Tx Driver Engine */
-+	wed_clr(dev, MTK_WED_CTRL,
-+		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
++	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
 +
  	for (i = 0; i < 100; i++) {
  		val = wed_r32(dev, MTK_WED_TX_BM_INTF);
  		if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
- 			break;
+@@ -1030,8 +1199,21 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  	}
--
+ 
  	mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
-+
 +	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN);
  	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
  
 +	/* 4. Reset WED WPDMA Tx Driver Engine */
 +	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-+				      MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
++				 MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
++
 +	wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
 +		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
 +		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
 +
-+	busy = !!(busy ||
-+		  mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-+					 MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
++	if(!busy)
++		mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
++				  MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY);
++
  	if (busy) {
  		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
  		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
-@@ -1065,6 +1221,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- 			MTK_WED_WPDMA_RESET_IDX_TX |
- 			MTK_WED_WPDMA_RESET_IDX_RX);
+@@ -1043,6 +1225,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  		wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0);
-+		if (dev->ver > MTK_WED_V1) {
-+			wed_w32(dev, MTK_WED_RESET_IDX,
-+				MTK_WED_RESET_WPDMA_IDX_RX);
-+			wed_w32(dev, MTK_WED_RESET_IDX, 0);
-+		}
-+	}
-+
-+	if (dev->ver > MTK_WED_V1) {
-+		dev->init_done = false;
-+		mtk_wed_rx_reset(dev);
  	}
  
++	dev->init_done = false;
++	if (dev->hw->version == 1)
++		return;
++
++	if (!busy) {
++		wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX);
++		wed_w32(dev, MTK_WED_RESET_IDX, 0);
++	}
++
++	mtk_wed_rx_reset(dev);
  }
-@@ -1101,13 +1267,15 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+ 
+ static int
+@@ -1062,7 +1254,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
  }
  
  static int
 -mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
-+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
-+		int idx, int size, bool reset)
++mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
++			   bool reset)
  {
- 	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
+ 	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ 	struct mtk_wed_ring *wdma;
+@@ -1071,8 +1264,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ 		return -EINVAL;
  
--	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
--			       dev->ver, true))
--		return -ENOMEM;
-+	if(!reset)
-+		if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+				       dev->ver, true))
-+			return -ENOMEM;
+ 	wdma = &dev->rx_wdma[idx];
+-	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size,
+-			       true))
++	if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
++					 desc_size, true))
+ 		return -ENOMEM;
  
  	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
- 		 wdma->desc_phys);
-@@ -1124,13 +1292,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -1090,7 +1283,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
  }
  
  static int
 -mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
-+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
-+	int idx, int size, bool reset)
++mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
++			   bool reset)
  {
- 	struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
+ 	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ 	struct mtk_wed_ring *wdma;
+@@ -1099,8 +1293,8 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ 		return -EINVAL;
  
+ 	wdma = &dev->tx_wdma[idx];
 -	if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
--			       dev->ver, true))
--		return -ENOMEM;
-+	if (!reset)
-+		if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+				       dev->ver, true))
-+			return -ENOMEM;
+-			       desc_size, true))
++	if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
++					 desc_size, true))
+ 		return -ENOMEM;
  
  	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
- 		 wdma->desc_phys);
-@@ -1140,7 +1310,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
- 		 MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0);
+@@ -1112,6 +1306,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
  	wdma_w32(dev,
  		 MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
--
+ 
 +	if (reset)
-+		mtk_wed_ring_reset(wdma->desc, MTK_WED_WDMA_RING_SIZE,
-+				   dev->ver, true);
- 	if (idx == 0)  {
- 		wed_w32(dev, MTK_WED_WDMA_RING_TX
- 			+ MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-@@ -1253,9 +1425,12 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++		mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true);
++
+ 	if (!idx)  {
+ 		wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE,
+ 			wdma->desc_phys);
+@@ -1267,9 +1464,12 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
  {
- 	int i, ret;
+ 	int i;
  
-+	if (dev->ver > MTK_WED_V1)
-+		ret = mtk_wed_rx_bm_alloc(dev);
++	if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev))
++		return;
 +
- 	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- 		if (!dev->tx_wdma[i].desc)
+ 	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
+ 		if (!dev->rx_wdma[i].desc)
 -			mtk_wed_wdma_rx_ring_setup(dev, i, 16);
 +			mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
  
+ 
  	mtk_wed_hw_init(dev);
+@@ -1278,10 +1478,9 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 	mtk_wed_set_ext_int(dev, true);
+ 
+ 	if (dev->hw->version == 1) {
+-		u32 val;
+-
+-		val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
+-		      FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
++		u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
++			  FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID,
++				     dev->hw->index);
  
-@@ -1347,10 +1522,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 		goto error;
+ 		val |= BIT(0) | (BIT(1) * !!dev->hw->index);
+ 		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
+@@ -1353,10 +1552,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 		goto out;
  
- 	if (dev->ver > MTK_WED_V1) {
--		ret = mtk_wed_rx_bm_alloc(dev);
+ 	if (mtk_wed_get_rx_capa(dev)) {
+-		ret = mtk_wed_rx_buffer_alloc(dev);
 -		if (ret)
--			goto error;
+-			goto out;
 -
  		ret = mtk_wed_rro_alloc(dev);
  		if (ret)
- 			goto error;
-@@ -1358,6 +1529,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 			goto out;
+@@ -1364,6 +1559,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  
  	mtk_wed_hw_init_early(dev);
  
@@ -609,10 +645,23 @@
 +	init_completion(&dev->wlan_reset_done);
 +	atomic_set(&dev->fe_reset, 0);
 +
- 	if (dev->ver == MTK_WED_V1)
+ 	if (hw->version == 1) {
  		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
  				   BIT(hw->index), 0);
-@@ -1374,7 +1549,8 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -1373,8 +1572,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	}
+ 
+ out:
+-	if (ret)
+-		mtk_wed_detach(dev);
++	if (ret) {
++		dev_err(dev->hw->dev, "failed to attach wed device\n");
++		__mtk_wed_detach(dev);
++	}
+ unlock:
+ 	mutex_unlock(&hw_lock);
+ 
+@@ -1382,7 +1583,8 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  }
  
  static int
@@ -622,65 +671,52 @@
  {
  	struct mtk_wed_ring *ring = &dev->tx_ring[idx];
  
-@@ -1392,10 +1568,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+@@ -1401,11 +1603,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ 	if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring)))
+ 		return -EINVAL;
  
- 	BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
- 
--	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1, true))
--		return -ENOMEM;
-+	if (!reset)
-+		if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
-+				       1, true))
-+			return -ENOMEM;
+-	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
+-			       sizeof(*ring->desc), true))
++	if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
++					 sizeof(*ring->desc), true))
+ 		return -ENOMEM;
  
 -	if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-+	if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
++	if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE,
++				       reset))
  		return -ENOMEM;
  
  	ring->reg_base = MTK_WED_RING_TX(idx);
-@@ -1443,21 +1621,24 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -1450,18 +1653,20 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
  }
  
  static int
 -mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
-+		int idx, void __iomem *regs, bool reset)
++mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs,
++		      bool reset)
  {
  	struct mtk_wed_ring *ring = &dev->rx_ring[idx];
  
- 	BUG_ON(idx > ARRAY_SIZE(dev->rx_ring));
+ 	if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring)))
+ 		return -EINVAL;
  
-+	if (!reset)
-+		if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
-+				       1, false))
-+			return -ENOMEM;
+-	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
+-			       sizeof(*ring->desc), false))
++	if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
++					 sizeof(*ring->desc), false))
+ 		return -ENOMEM;
  
--	if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, 1, false))
--		return -ENOMEM;
--
 -	if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-+	if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
++	if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE,
++				       reset))
  		return -ENOMEM;
  
  	ring->reg_base = MTK_WED_RING_RX_DATA(idx);
- 	ring->wpdma = regs;
-+	dev->hw->ring_num = idx + 1;
- 
- 	/* WPDMA ->  WED */
- 	wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 8ef5253..490873c 100644
+index 1bfd96f..2ce1a5b 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.h
-@@ -47,6 +47,7 @@ struct mtk_wed_hw {
- 	u32 num_flows;
- 	u32 wdma_phy;
- 	char dirname[5];
-+	int ring_num;
- 	int irq;
- 	int index;
- 	u32 ver;
-@@ -158,6 +159,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -160,6 +160,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  void mtk_wed_exit(void);
  int mtk_wed_flow_add(int index);
  void mtk_wed_flow_remove(int index);
@@ -690,7 +726,7 @@
  #else
  static inline void
  mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
-@@ -175,6 +179,13 @@ static inline int mtk_wed_flow_add(int index)
+@@ -178,6 +181,13 @@ static inline int mtk_wed_flow_add(int index)
  static inline void mtk_wed_flow_remove(int index)
  {
  }
@@ -705,10 +741,10 @@
  
  #ifdef CONFIG_DEBUG_FS
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 31871f7..403a36b 100644
+index a79305f..645b8b1 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -38,11 +38,15 @@ struct mtk_wdma_desc {
+@@ -32,11 +32,15 @@ struct mtk_wdma_desc {
  
  #define MTK_WED_RESET					0x008
  #define MTK_WED_RESET_TX_BM				BIT(0)
@@ -724,20 +760,16 @@
  #define MTK_WED_RESET_WDMA_RX_DRV			BIT(17)
  #define MTK_WED_RESET_WDMA_INT_AGENT			BIT(19)
  #define MTK_WED_RESET_RX_RRO_QM				BIT(20)
-@@ -185,7 +189,12 @@ struct mtk_wdma_desc {
- 
+@@ -174,6 +178,8 @@ struct mtk_wdma_desc {
  #define MTK_WED_RESET_IDX				0x20c
  #define MTK_WED_RESET_IDX_TX				GENMASK(3, 0)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_RESET_IDX_RX				GENMASK(7, 6)
-+#else
  #define MTK_WED_RESET_IDX_RX				GENMASK(17, 16)
-+#endif
++#define MTK_WED_RESET_IDX_RX_V2				GENMASK(7, 6)
 +#define MTK_WED_RESET_WPDMA_IDX_RX			GENMASK(31, 30)
  
  #define MTK_WED_TX_MIB(_n)				(0x2a0 + (_n) * 4)
  #define MTK_WED_RX_MIB(_n)				(0x2e0 + (_n) * 4)
-@@ -299,6 +308,9 @@ struct mtk_wdma_desc {
+@@ -287,6 +293,9 @@ struct mtk_wdma_desc {
  
  #define MTK_WED_WPDMA_RX_D_GLO_CFG			0x75c
  #define MTK_WED_WPDMA_RX_D_RX_DRV_EN			BIT(0)
@@ -748,10 +780,10 @@
  #define MTK_WED_WPDMA_RX_D_RXD_READ_LEN			GENMASK(31, 24)
  
 diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index e8fca31..98ed390 100644
+index 658f392..6772ea8 100644
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -163,18 +163,23 @@ struct mtk_wed_device {
+@@ -151,16 +151,21 @@ struct mtk_wed_device {
  		void (*release_rx_buf)(struct mtk_wed_device *wed);
  		void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
  					   struct mtk_wed_wo_rx_stats *stats);
@@ -769,60 +801,60 @@
  	int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
 -			     void __iomem *regs);
 +			     void __iomem *regs, bool reset);
- 	int (*txfree_ring_setup)(struct mtk_wed_device *dev,
- 				 void __iomem *regs);
  	int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
--				 void __iomem *regs);
+-			     void __iomem *regs);
 +			     void __iomem *regs, bool reset);
+ 	int (*txfree_ring_setup)(struct mtk_wed_device *dev,
+ 				 void __iomem *regs);
  	int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- 			  void *data, int len);
- 	void (*detach)(struct mtk_wed_device *dev);
-@@ -228,12 +233,13 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+@@ -216,8 +221,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
  #define mtk_wed_device_active(_dev) !!(_dev)->ops
  #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
  #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask)
 -#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \
 -	(_dev)->ops->tx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
 +#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \
-+	(_dev)->ops->tx_ring_setup(_dev, _ring, _regs,  _reset)
++	(_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset)
  #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
  	(_dev)->ops->txfree_ring_setup(_dev, _regs)
--#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
--	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
-+	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset)
- #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
- 	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
  #define mtk_wed_device_reg_read(_dev, _reg) \
-@@ -244,6 +250,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+@@ -228,12 +233,14 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
  	(_dev)->ops->irq_get(_dev, _mask)
  #define mtk_wed_device_irq_set_mask(_dev, _mask) \
  	(_dev)->ops->irq_set_mask(_dev, _mask)
-+#define mtk_wed_device_dma_reset(_dev) \
-+	(_dev)->ops->reset_dma(_dev)
+-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
+-	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
++	(_dev)->ops->rx_ring_setup(_dev, _ring, _regs, reset)
  #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
  	(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
+ 	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
++#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
++#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
  #else
-@@ -253,14 +261,15 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -241,15 +248,17 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
  }
  #define mtk_wed_device_detach(_dev) do {} while (0)
  #define mtk_wed_device_start(_dev, _mask) do {} while (0)
 -#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_stop(_dev) do {} while (0)
 +#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
  #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
--#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
--#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
  #define mtk_wed_device_reg_read(_dev, _reg) 0
  #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
  #define mtk_wed_device_irq_get(_dev, _mask) 0
  #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
-+#define mtk_wed_device_dma_reset(_dev) do {} while (0)
+-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
  #define mtk_wed_device_ppe_check(_dev, _hash)  do {} while (0)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
++#define mtk_wed_device_stop(_dev) do {} while (0)
++#define mtk_wed_device_dma_reset(_dev) do {} while (0)
  #endif
  
+ #endif
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
index b547328..18c6d2a 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
@@ -1,7 +1,7 @@
-From 84fd451dd7379943e6957e9ceb749be4d6c41540 Mon Sep 17 00:00:00 2001
+From 7feee53fdfd481fc2beb02739ccd0e87f1c96b7a Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:07:14 +0800
-Subject: [PATCH 11/22] ethernet-update-ppe-backward-compatible-two-way-hash
+Subject: [PATCH 10/24] ethernet-update-ppe-backward-compatible-two-way-hash
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 ++++++++-
@@ -11,10 +11,10 @@
  4 files changed, 29 insertions(+), 11 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index c1399c5..bd622d3 100644
+index a24b223..e8837b6 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5252,7 +5252,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5799,7 +5799,8 @@ static int mtk_probe(struct platform_device *pdev)
  
  		for (i = 0; i < eth->ppe_num; i++) {
  			eth->ppe[i] = mtk_ppe_init(eth,
@@ -24,7 +24,7 @@
  			if (!eth->ppe[i]) {
  				err = -ENOMEM;
  				goto err_free_dev;
-@@ -5359,6 +5360,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5913,6 +5914,7 @@ static const struct mtk_soc_data mt2701_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -32,7 +32,7 @@
  	.offload_version = 2,
  	.rss_num = 0,
  	.txrx = {
-@@ -5377,6 +5379,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5931,6 +5933,7 @@ static const struct mtk_soc_data mt7621_data = {
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -40,7 +40,7 @@
  	.offload_version = 2,
  	.rss_num = 0,
  	.txrx = {
-@@ -5396,6 +5399,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5950,6 +5953,7 @@ static const struct mtk_soc_data mt7622_data = {
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -48,7 +48,7 @@
  	.offload_version = 2,
  	.rss_num = 0,
  	.txrx = {
-@@ -5414,6 +5418,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5968,6 +5972,7 @@ static const struct mtk_soc_data mt7623_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -56,7 +56,7 @@
  	.offload_version = 2,
  	.rss_num = 0,
  	.txrx = {
-@@ -5451,6 +5456,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6005,6 +6010,7 @@ static const struct mtk_soc_data mt7986_data = {
  	.required_clks = MT7986_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -64,7 +64,7 @@
  	.offload_version = 2,
  	.rss_num = 4,
  	.txrx = {
-@@ -5470,6 +5476,8 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6024,6 +6030,8 @@ static const struct mtk_soc_data mt7981_data = {
  	.required_clks = MT7981_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -74,10 +74,10 @@
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 960b979..68b8ab1 100644
+index 9099dea..b4f04e2 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1679,6 +1679,7 @@ struct mtk_soc_data {
+@@ -1732,6 +1732,7 @@ struct mtk_soc_data {
  	u64		caps;
  	u64		required_clks;
  	bool		required_pctl;
@@ -86,7 +86,7 @@
  	netdev_features_t hw_features;
  	bool		has_sram;
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 96c15b3..4da7e7a 100755
+index c9ee505..569bf34 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -88,7 +88,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable)
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
index c516fd6..6a2a6f6 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
@@ -1,7 +1,7 @@
-From 77bdae190ded4dfafa80dfaf04a77018e33e233c Mon Sep 17 00:00:00 2001
+From 4eaba588e0c730d6188f5f1b667a55d1b9ca0fe6 Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:09:23 +0800
-Subject: [PATCH 12/22] flow-offload-add-mtkhnat-flow-accounting
+Subject: [PATCH 11/24] flow-offload-add-mtkhnat-flow-accounting
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  11 +-
@@ -15,10 +15,10 @@
  8 files changed, 191 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index bd622d3..9d8ce07 100644
+index e8837b6..9cd306d 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5253,7 +5253,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5800,7 +5800,8 @@ static int mtk_probe(struct platform_device *pdev)
  		for (i = 0; i < eth->ppe_num; i++) {
  			eth->ppe[i] = mtk_ppe_init(eth,
  						   eth->base + MTK_ETH_PPE_BASE + i * 0x400,
@@ -28,7 +28,7 @@
  			if (!eth->ppe[i]) {
  				err = -ENOMEM;
  				goto err_free_dev;
-@@ -5360,6 +5361,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5914,6 +5915,7 @@ static const struct mtk_soc_data mt2701_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -36,7 +36,7 @@
  	.hash_way = 2,
  	.offload_version = 2,
  	.rss_num = 0,
-@@ -5379,6 +5381,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5933,6 +5935,7 @@ static const struct mtk_soc_data mt7621_data = {
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -44,7 +44,7 @@
  	.hash_way = 2,
  	.offload_version = 2,
  	.rss_num = 0,
-@@ -5399,6 +5402,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5953,6 +5956,7 @@ static const struct mtk_soc_data mt7622_data = {
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -52,7 +52,7 @@
  	.hash_way = 2,
  	.offload_version = 2,
  	.rss_num = 0,
-@@ -5418,6 +5422,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5972,6 +5976,7 @@ static const struct mtk_soc_data mt7623_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
@@ -60,7 +60,7 @@
  	.hash_way = 2,
  	.offload_version = 2,
  	.rss_num = 0,
-@@ -5438,6 +5443,7 @@ static const struct mtk_soc_data mt7629_data = {
+@@ -5992,6 +5997,7 @@ static const struct mtk_soc_data mt7629_data = {
  	.required_clks = MT7629_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -68,7 +68,7 @@
  	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5456,6 +5462,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6010,6 +6016,7 @@ static const struct mtk_soc_data mt7986_data = {
  	.required_clks = MT7986_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -76,7 +76,7 @@
  	.hash_way = 4,
  	.offload_version = 2,
  	.rss_num = 4,
-@@ -5476,6 +5483,7 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6030,6 +6037,7 @@ static const struct mtk_soc_data mt7981_data = {
  	.required_clks = MT7981_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -84,7 +84,7 @@
  	.hash_way = 4,
  	.offload_version = 2,
  	.rss_num = 4,
-@@ -5513,6 +5521,7 @@ static const struct mtk_soc_data rt5350_data = {
+@@ -6067,6 +6075,7 @@ static const struct mtk_soc_data rt5350_data = {
  	.required_clks = MT7628_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
@@ -93,10 +93,10 @@
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 68b8ab1..101c233 100644
+index b4f04e2..5f90765 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1683,6 +1683,7 @@ struct mtk_soc_data {
+@@ -1736,6 +1736,7 @@ struct mtk_soc_data {
  	u8		offload_version;
  	netdev_features_t hw_features;
  	bool		has_sram;
@@ -105,7 +105,7 @@
  		u32	txd_size;
  		u32	rxd_size;
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 4da7e7a..f55a95c 100755
+index 569bf34..94e03b2 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_ppe *ppe)
@@ -446,10 +446,10 @@
  #define MTK_PPE_MIB_CACHE_CTL_EN		BIT(0)
  #define MTK_PPE_MIB_CACHE_CTL_FLUSH		BIT(2)
 diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
-index 2cab008..1defb15 100644
+index e4c7db9..aae37f5 100644
 --- a/net/netfilter/xt_FLOWOFFLOAD.c
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -766,7 +766,7 @@ static int __init xt_flowoffload_tg_init(void)
+@@ -772,7 +772,7 @@ static int __init xt_flowoffload_tg_init(void)
  	if (ret)
  		goto cleanup;
  
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
index d51f24f..4110b83 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -1,19 +1,19 @@
-From 9e21d6fa97e93cb2ba9b923810666ddaf7a981ee Mon Sep 17 00:00:00 2001
+From 0247c9d63f56bbe34f4205f986957b5036a9a4d8 Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:11:03 +0800
-Subject: [PATCH 13/22] flow-offload-add-mtkhnat-qdma-qos
+Subject: [PATCH 12/24] flow-offload-add-mtkhnat-qdma-qos
 
 ---
  drivers/net/ethernet/mediatek/Makefile        |   2 +-
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  10 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  48 ++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  50 ++
  drivers/net/ethernet/mediatek/mtk_ppe.c       |  48 +-
  drivers/net/ethernet/mediatek/mtk_ppe.h       |   4 +
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |  28 +-
  .../net/ethernet/mediatek/mtk_qdma_debugfs.c  | 439 ++++++++++++++++++
  include/net/flow_offload.h                    |   1 +
  net/netfilter/nf_flow_table_offload.c         |   4 +-
- 9 files changed, 593 insertions(+), 6 deletions(-)
+ 9 files changed, 581 insertions(+), 5 deletions(-)
  create mode 100644 drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
 
 diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
@@ -30,10 +30,10 @@
  ifdef CONFIG_DEBUG_FS
  mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 9d8ce07..0f6613b 100644
+index 9cd306d..1660fd9 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5266,6 +5266,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5813,6 +5813,8 @@ static int mtk_probe(struct platform_device *pdev)
  		}
  
  		mtk_ppe_debugfs_init(eth);
@@ -42,7 +42,7 @@
  	}
  
  	for (i = 0; i < MTK_MAX_DEVS; i++) {
-@@ -5371,6 +5373,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5925,6 +5927,7 @@ static const struct mtk_soc_data mt2701_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -50,7 +50,7 @@
  	},
  };
  
-@@ -5391,6 +5394,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5945,6 +5948,7 @@ static const struct mtk_soc_data mt7621_data = {
  		.rxd_size = sizeof(struct mtk_rx_dma),
  		.dma_max_len = MTK_TX_DMA_BUF_LEN,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -58,7 +58,7 @@
  	},
  };
  
-@@ -5412,6 +5416,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5966,6 +5970,7 @@ static const struct mtk_soc_data mt7622_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -66,7 +66,7 @@
  	},
  };
  
-@@ -5432,6 +5437,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5986,6 +5991,7 @@ static const struct mtk_soc_data mt7623_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -74,7 +74,7 @@
  	},
  };
  
-@@ -5472,6 +5478,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6026,6 +6032,7 @@ static const struct mtk_soc_data mt7986_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -82,7 +82,7 @@
  	},
  };
  
-@@ -5493,6 +5500,7 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6047,6 +6054,7 @@ static const struct mtk_soc_data mt7981_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -90,7 +90,7 @@
  	},
  };
  
-@@ -5511,6 +5519,7 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -6065,6 +6073,7 @@ static const struct mtk_soc_data mt7988_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -98,7 +98,7 @@
  	},
  };
  
-@@ -5529,6 +5538,7 @@ static const struct mtk_soc_data rt5350_data = {
+@@ -6083,6 +6092,7 @@ static const struct mtk_soc_data rt5350_data = {
  		.rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA,
  		.dma_max_len = MTK_TX_DMA_BUF_LEN,
  		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -107,10 +107,10 @@
  };
  
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 101c233..7ea380e 100644
+index 5f90765..02ca0b2 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -458,6 +471,9 @@
+@@ -487,6 +487,9 @@
  #define FC_THRES_DROP_EN	(7 << 16)
  #define FC_THRES_MIN		0x4444
  
@@ -120,7 +120,7 @@
  /* QDMA Interrupt Status Register */
  #define MTK_QDMA_INT_STATUS	(QDMA_BASE + 0x218)
  #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-@@ -494,6 +510,11 @@
+@@ -530,6 +533,11 @@
  /* QDMA Interrupt Mask Register */
  #define MTK_QDMA_HRED2		(QDMA_BASE + 0x244)
  
@@ -132,7 +132,7 @@
  /* QDMA TX Forward CPU Pointer Register */
  #define MTK_QTX_CTX_PTR		(QDMA_BASE +0x300)
  
-@@ -521,6 +542,14 @@
+@@ -557,6 +565,14 @@
  /* QDMA FQ Free Page Buffer Length Register */
  #define MTK_QDMA_FQ_BLEN	(QDMA_BASE +0x32c)
  
@@ -147,7 +147,7 @@
  /* WDMA Registers */
  #define MTK_WDMA_CTX_PTR(x)	(WDMA_BASE(x) + 0x8)
  #define MTK_WDMA_DTX_PTR(x)	(WDMA_BASE(x) + 0xC)
-@@ -1690,6 +1719,7 @@ struct mtk_soc_data {
+@@ -1743,6 +1759,7 @@ struct mtk_soc_data {
  		u32	rx_dma_l4_valid;
  		u32	dma_max_len;
  		u32	dma_len_offset;
@@ -155,7 +155,7 @@
  	} txrx;
  };
  
-@@ -1879,6 +1909,7 @@ struct mtk_eth {
+@@ -1936,6 +1953,7 @@ struct mtk_eth {
  	spinlock_t			syscfg0_lock;
  	struct timer_list		mtk_dma_monitor_timer;
  
@@ -163,7 +163,7 @@
  	u8				ppe_num;
  	struct mtk_ppe			*ppe[MTK_MAX_PPE_NUM];
  	struct rhashtable		flow_table;
-@@ -1936,6 +1967,36 @@ extern const struct of_device_id of_mtk_match[];
+@@ -1994,6 +2012,36 @@ extern const struct of_device_id of_mtk_match[];
  extern u32 mtk_hwlro_stats_ebl;
  extern u32 dbg_show_level;
  
@@ -200,7 +200,7 @@
  /* read the hardware status register */
  void mtk_stats_update_mac(struct mtk_mac *mac);
  
-@@ -1969,4 +2028,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+@@ -2027,4 +2075,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
  u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
  
  int mtk_ppe_debugfs_init(struct mtk_eth *eth);
@@ -208,7 +208,7 @@
 +int mtk_qdma_debugfs_init(struct mtk_eth *eth);
  #endif /* MTK_ETH_H */
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index f55a95c..6d6c1e4 100755
+index 94e03b2..8388f65 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -128,7 +128,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable)
@@ -366,7 +366,7 @@
  		return err;
 diff --git a/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
 new file mode 100644
-index 0000000..3a7c585
+index 0000000..d76b3c5
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
 @@ -0,0 +1,439 @@
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3013-flow-offload-ovs-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3013-flow-offload-ovs-support.patch
index a164d1a..5220a63 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3013-flow-offload-ovs-support.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3013-flow-offload-ovs-support.patch
@@ -1,7 +1,7 @@
-From 842a435bd21807447504a387e5ebb8071b0db93f Mon Sep 17 00:00:00 2001
+From f3112e335a7f95aeb3d834962de813baadc1f620 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Mon, 18 Sep 2023 11:11:41 +0800
-Subject: [PATCH 14/22] flow-offload-ovs-support
+Subject: [PATCH 13/24] flow-offload-ovs-support
 
 ---
  net/openvswitch/vport-internal_dev.c | 46 ++++++++++++++++++++++++++++
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3014-update-net-bridge-for-bridger.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3014-update-net-bridge-for-bridger.patch
index 89e664f..a23233f 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3014-update-net-bridge-for-bridger.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3014-update-net-bridge-for-bridger.patch
@@ -1,7 +1,7 @@
-From 120baca4e8b019d03c8d1a29012cea911629247a Mon Sep 17 00:00:00 2001
+From 552ae5e27e936eb74dd563485ab77f40b96a61a5 Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:13:51 +0800
-Subject: [PATCH 15/22] update-net-bridge-for-bridger
+Subject: [PATCH 14/24] update-net-bridge-for-bridger
 
 ---
  include/net/switchdev.h        |   2 +
@@ -1805,10 +1805,10 @@
 +	return false;
 +}
 diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index da1ef00..b896f71 100644
+index 4eed989..de75eb2 100644
 --- a/net/core/rtnetlink.c
 +++ b/net/core/rtnetlink.c
-@@ -1998,6 +1998,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -2004,6 +2004,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
  				goto cont;
  			if (idx < s_idx)
  				goto cont;
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
index bedf09e..c44e494 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
@@ -1,7 +1,7 @@
-From 5481f7ecbd3cfffd8234bc8e952a6e07f42de76c Mon Sep 17 00:00:00 2001
+From a326344938c515068241eb66580f57255258d9c6 Mon Sep 17 00:00:00 2001
 From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
 Date: Tue, 21 Nov 2023 16:42:01 +0800
-Subject: [PATCH 16/22] ethernet-update-ppe-from-netsys2-to-netsys3
+Subject: [PATCH 15/24] ethernet-update-ppe-from-netsys2-to-netsys3
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 14 ++++---
@@ -13,10 +13,10 @@
  6 files changed, 85 insertions(+), 22 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 850bc4f..8910d40 100644
+index 1660fd9..a3ed175 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2248,17 +2248,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2447,17 +2447,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  			skb_checksum_none_assert(skb);
  		skb->protocol = eth_type_trans(skb, netdev);
  
@@ -37,8 +37,8 @@
 +#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
  		reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
  		if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
- 			for (i = 0; i < eth->ppe_num; i++) {
-@@ -5290,7 +5290,8 @@ static int mtk_probe(struct platform_device *pdev)
+ 			mtk_ppe_check_skb(eth->ppe[0], skb,
+@@ -5799,7 +5799,8 @@ static int mtk_probe(struct platform_device *pdev)
  
  		for (i = 0; i < eth->ppe_num; i++) {
  			eth->ppe[i] = mtk_ppe_init(eth,
@@ -48,7 +48,7 @@
  						   2, eth->soc->hash_way, i,
  						   eth->soc->has_accounting);
  			if (!eth->ppe[i]) {
-@@ -5557,6 +5558,9 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -6066,6 +6067,9 @@ static const struct mtk_soc_data mt7988_data = {
  	.required_clks = MT7988_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = true,
@@ -59,10 +59,10 @@
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 9c77f14..c7d36c5 100644
+index 02ca0b2..f9dda59 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -134,9 +134,10 @@
+@@ -137,9 +137,10 @@
  #define MTK_GDMA_UCS_EN		BIT(20)
  #define MTK_GDMA_STRP_CRC	BIT(16)
  #define MTK_GDMA_TO_PDMA	0x0
@@ -74,7 +74,7 @@
  #else
  #define MTK_GDMA_TO_PPE0	0x4444
  #endif
-@@ -1978,14 +1979,14 @@ extern u32 dbg_show_level;
+@@ -2014,14 +2015,14 @@ extern u32 dbg_show_level;
  
  static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
  {
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
index 121db94..14639c4 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
@@ -1,21 +1,21 @@
-From d3183ad9ed0a8a35047a37f30d85f920a729897c Mon Sep 17 00:00:00 2001
+From 743b10e8e2a17c904f27cf78d46aea64193fc41c Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:16:18 +0800
-Subject: [PATCH 17/22] mediatek-ethernet-add-wifi2wifi-offload-support
+Subject: [PATCH 16/24] mediatek-ethernet-add-wifi2wifi-offload-support
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  2 ++
  .../net/ethernet/mediatek/mtk_ppe_offload.c   | 35 +++++++++++++------
  drivers/net/ethernet/mediatek/mtk_wed.c       | 13 +++++++
- include/linux/soc/mediatek/mtk_wed.h          |  6 +++-
- 4 files changed, 45 insertions(+), 11 deletions(-)
+ include/linux/soc/mediatek/mtk_wed.h          |  5 +++
+ 4 files changed, 45 insertions(+), 10 deletions(-)
  mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe_offload.c
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 23c5f49..ee89b4c 100644
+index f9dda59..88d2f46 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -2027,6 +2027,8 @@ void mtk_usxgmii_link_poll(struct work_struct *work);
+@@ -2072,6 +2072,8 @@ void mtk_usxgmii_link_poll(struct work_struct *work);
  int mtk_eth_offload_init(struct mtk_eth *eth, int id);
  int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
  		     void *type_data);
@@ -100,15 +100,15 @@
  		return -EOPNOTSUPP;
  	}
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index ae31412..3e760f7 100644
+index 5dd1182..68eedd3 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -1733,6 +1733,18 @@ void mtk_wed_flow_remove(int index)
+@@ -1766,6 +1766,18 @@ void mtk_wed_flow_remove(int index)
  	mutex_unlock(&hw_lock);
  }
  
 +static int mtk_wed_eth_setup_tc(struct mtk_wed_device *wed, struct net_device *dev,
-+		int type, void *type_data)
++				int type, void *type_data)
 +{
 +	switch (type) {
 +	case TC_SETUP_BLOCK:
@@ -120,9 +120,9 @@
 +}
 +
  void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- 			void __iomem *wdma, u32 wdma_phy, int index)
- 
-@@ -1751,6 +1763,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 		    void __iomem *wdma, phys_addr_t wdma_phy,
+ 		    int index)
+@@ -1785,6 +1797,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  		.irq_get = mtk_wed_irq_get,
  		.irq_set_mask = mtk_wed_irq_set_mask,
  		.detach = mtk_wed_detach,
@@ -131,36 +131,35 @@
  	};
  	struct device_node *eth_np = eth->dev->of_node;
 diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 98ed390..27cf284 100644
+index 6772ea8..470beb2 100644
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -183,7 +183,8 @@ struct mtk_wed_ops {
- 	int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- 			  void *data, int len);
+@@ -173,6 +173,8 @@ struct mtk_wed_ops {
  	void (*detach)(struct mtk_wed_device *dev);
--
+ 	void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
+ 			  u32 reason, u32 hash);
 +	int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
-+			 int type, void *type_data);
++			int type, void *type_data);
+ 
  	void (*stop)(struct mtk_wed_device *dev);
  	void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
- 	void (*reset_dma)(struct mtk_wed_device *dev);
-@@ -232,6 +233,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- #define mtk_wed_device_active(_dev) !!(_dev)->ops
- #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
+@@ -241,6 +243,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ 	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
+ #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
 +#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
 +	(_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
- #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask)
- #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \
-@@ -270,6 +273,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_irq_get(_dev, _mask) 0
- #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
+ #else
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -259,6 +263,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
+ #define mtk_wed_device_stop(_dev) do {} while (0)
  #define mtk_wed_device_dma_reset(_dev) do {} while (0)
 +#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
- #define mtk_wed_device_ppe_check(_dev, _hash)  do {} while (0)
  #endif
  
+ #endif
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3017-flow-offload-add-mtkhnat-dscp.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3017-flow-offload-add-mtkhnat-dscp.patch
index 478a7a9..070bb7c 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3017-flow-offload-add-mtkhnat-dscp.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3017-flow-offload-add-mtkhnat-dscp.patch
@@ -1,7 +1,7 @@
-From 3e4d44d8da90b9ba20abc5cec255d92b67e3fb00 Mon Sep 17 00:00:00 2001
+From 8c918e858df4b7cb12ea185acf23e83bae883cd2 Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 11:17:24 +0800
-Subject: [PATCH 18/22] flow-offload-add-mtkhnat-dscp
+Subject: [PATCH 17/24] flow-offload-add-mtkhnat-dscp
 
 ---
  drivers/net/ethernet/mediatek/mtk_ppe.c       | 11 +++++++
@@ -13,10 +13,10 @@
  6 files changed, 64 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 446acca..384e811 100755
+index 184e29d..0e9c0bd 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -435,6 +435,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+@@ -446,6 +446,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
  
  	return 0;
  }
@@ -84,10 +84,10 @@
  
  	err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
 diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index feac793..97a277d 100644
+index 7374cb2..d5dd3fe 100644
 --- a/include/net/netfilter/nf_flow_table.h
 +++ b/include/net/netfilter/nf_flow_table.h
-@@ -36,6 +36,7 @@ struct nf_flow_key {
+@@ -38,6 +38,7 @@ struct nf_flow_key {
  	};
  	struct flow_dissector_key_tcp			tcp;
  	struct flow_dissector_key_ports			tp;
@@ -95,7 +95,7 @@
  } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
  
  struct nf_flow_match {
-@@ -145,6 +146,7 @@ struct flow_offload_tuple {
+@@ -147,6 +148,7 @@ struct flow_offload_tuple {
  			u8		h_dest[ETH_ALEN];
  		} out;
  	};
@@ -132,7 +132,7 @@
  }
  
 diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
-index 1defb15..d4aecab 100644
+index aae37f5..5364a32 100644
 --- a/net/netfilter/xt_FLOWOFFLOAD.c
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
 @@ -49,6 +49,35 @@ static DEFINE_SPINLOCK(hooks_lock);
@@ -171,7 +171,7 @@
  static unsigned int
  xt_flowoffload_net_hook(void *priv, struct sk_buff *skb,
  			const struct nf_hook_state *state)
-@@ -617,6 +646,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+@@ -623,6 +652,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
  	if (flow_offload_route_init(flow, &route) < 0)
  		goto err_flow_add;
  
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3018-flow-offload-add-mtkhnat-netlink.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3018-flow-offload-add-mtkhnat-netlink.patch
index 3bb7e7a..ff6f58f 100644
--- a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3018-flow-offload-add-mtkhnat-netlink.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3018-flow-offload-add-mtkhnat-netlink.patch
@@ -1,7 +1,7 @@
-From 6bda18f107acbf04f01c18ad5964be6f7404d3cf Mon Sep 17 00:00:00 2001
+From 122cb2a2ae7ececd20412083b5bb9bfd6f9c8d26 Mon Sep 17 00:00:00 2001
 From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 13:14:08 +0800
-Subject: [PATCH 19/22] flow-offload-add-mtkhnat-netlink
+Subject: [PATCH 18/24] flow-offload-add-mtkhnat-netlink
 
 ---
  include/net/netfilter/nf_flow_table.h    |   1 +
@@ -14,10 +14,10 @@
  create mode 100644 net/netfilter/nf_flow_table_netlink.c
 
 diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index 97a277d..3490d90 100644
+index d5dd3fe..f2bce73 100644
 --- a/include/net/netfilter/nf_flow_table.h
 +++ b/include/net/netfilter/nf_flow_table.h
-@@ -277,6 +277,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
+@@ -279,6 +279,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
  void nf_flow_table_free(struct nf_flowtable *flow_table);
  
  void flow_offload_teardown(struct flow_offload *flow);
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch
new file mode 100644
index 0000000..c3aac60
--- /dev/null
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch
@@ -0,0 +1,3817 @@
+From 3519673178423e9b7271782fd1a66f42cce88d19 Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Mon, 18 Sep 2023 13:21:15 +0800
+Subject: [PATCH 19/24] mtk:wed:add wed3 support
+
+---
+ arch/arm64/boot/dts/mediatek/mt7988.dtsi      |  152 ++-
+ .../dts/mediatek/mt7988a-dsa-10g-spim-nor.dts |   16 +-
+ .../dts/mediatek/mt7988d-dsa-10g-spim-nor.dts |   16 +-
+ drivers/net/ethernet/mediatek/mtk_ppe.c       |   17 +-
+ drivers/net/ethernet/mediatek/mtk_ppe.h       |    2 +-
+ .../net/ethernet/mediatek/mtk_ppe_offload.c   |    9 +-
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 1192 +++++++++++++----
+ drivers/net/ethernet/mediatek/mtk_wed.h       |   73 +-
+ .../net/ethernet/mediatek/mtk_wed_debugfs.c   |  584 +++++++-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c   |   40 +-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.h   |    7 +-
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h  |  353 ++++-
+ include/linux/netdevice.h                     |    7 +
+ include/linux/soc/mediatek/mtk_wed.h          |   77 +-
+ 14 files changed, 2146 insertions(+), 399 deletions(-)
+ mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+index 7e96640..3368240 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+@@ -193,44 +193,49 @@
+ 		status = "disabled";
+ 	};
+ 
+-	wed: wed@15010000 {
+-		compatible = "mediatek,wed";
+-		wed_num = <3>;
+-		/* add this property for wed get the pci slot number. */
+-		pci_slot_map = <0>, <1>, <2>;
+-		reg = <0 0x15010000 0 0x2000>,
+-		      <0 0x15012000 0 0x2000>,
+-		      <0 0x15014000 0 0x2000>;
++	wed0: wed@15010000 {
++		compatible = "mediatek,mt7988-wed",
++			     "syscon";
++		reg = <0 0x15010000 0 0x2000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+-	};
+-
+-	wed2: wed2@15012000 {
+-		compatible = "mediatek,wed2";
+-		wed_num = <3>;
+-		/* add this property for wed get the pci slot number. */
+-		reg = <0 0x15010000 0 0x2000>,
+-		      <0 0x15012000 0 0x2000>,
+-		      <0 0x15014000 0 0x2000>;
++		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
++		mediatek,wed_pcie = <&wed_pcie>;
++		mediatek,ap2woccif = <&ap2woccif0>;
++		mediatek,wocpu_ilm = <&wocpu0_ilm>;
++		mediatek,wocpu_dlm = <&wocpu0_dlm>;
++		mediatek,wocpu_boot = <&cpu0_boot>;
++		mediatek,wocpu_emi = <&wocpu0_emi>;
++		mediatek,wocpu_data = <&wocpu_data>;
++	};
++
++	wed1: wed@15012000 {
++		compatible = "mediatek,mt7988-wed",
++                             "syscon";
++		reg = <0 0x15012000 0 0x2000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+-	};
+-
+-	wed3: wed3@15014000 {
+-		compatible = "mediatek,wed3";
+-		wed_num = <3>;
+-		/* add this property for wed get the pci slot number. */
+-		reg = <0 0x15010000 0 0x2000>,
+-		      <0 0x15012000 0 0x2000>,
+-		      <0 0x15014000 0 0x2000>;
++		interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++		mediatek,wed_pcie = <&wed_pcie>;
++		mediatek,ap2woccif = <&ap2woccif1>;
++		mediatek,wocpu_ilm = <&wocpu1_ilm>;
++		mediatek,wocpu_dlm = <&wocpu1_dlm>;
++		mediatek,wocpu_boot = <&cpu1_boot>;
++		mediatek,wocpu_emi = <&wocpu1_emi>;
++		mediatek,wocpu_data = <&wocpu_data>;
++	};
++
++	wed2: wed@15014000 {
++		compatible = "mediatek,mt7988-wed",
++                             "syscon";
++		reg = <0 0x15014000 0 0x2000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
++		interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
++		mediatek,wed_pcie = <&wed_pcie>;
++		mediatek,ap2woccif = <&ap2woccif2>;
++		mediatek,wocpu_ilm = <&wocpu2_ilm>;
++		mediatek,wocpu_dlm = <&wocpu2_dlm>;
++		mediatek,wocpu_boot = <&cpu2_boot>;
++		mediatek,wocpu_emi = <&wocpu2_emi>;
++		mediatek,wocpu_data = <&wocpu_data>;
+ 	};
+ 
+ 	wdma: wdma@15104800 {
+@@ -240,15 +245,25 @@
+ 		      <0 0x15105000 0 0x400>;
+ 	};
+ 
+-	ap2woccif: ap2woccif@151A5000 {
+-		compatible = "mediatek,ap2woccif";
+-		reg = <0 0x151A5000 0 0x1000>,
+-		      <0 0x152A5000 0 0x1000>,
+-		      <0 0x153A5000 0 0x1000>;
++	ap2woccif0: ap2woccif@151A5000 {
++		compatible = "mediatek,ap2woccif", "syscon";
++		reg = <0 0x151A5000 0 0x1000>;
++		interrupt-parent = <&gic>;
++		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
++	};
++
++	ap2woccif1: ap2woccif@152A5000 {
++		compatible = "mediatek,ap2woccif", "syscon";
++		reg = <0 0x152A5000 0 0x1000>;
+ 		interrupt-parent = <&gic>;
+-		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+-			     <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
++		interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
++	};
++
++	ap2woccif2: ap2woccif@153A5000 {
++		compatible = "mediatek,ap2woccif", "syscon";
++		reg = <0 0x153A5000 0 0x1000>;
++		interrupt-parent = <&gic>;
++		interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+ 	};
+ 
+ 	wocpu0_ilm: wocpu0_ilm@151E0000 {
+@@ -256,31 +271,53 @@
+ 		reg = <0 0x151E0000 0 0x8000>;
+ 	};
+ 
+-	wocpu1_ilm: wocpu1_ilm@152E0000 {
+-		compatible = "mediatek,wocpu1_ilm";
++	wocpu1_ilm: wocpu_ilm@152E0000 {
++		compatible = "mediatek,wocpu_ilm";
+ 		reg = <0 0x152E0000 0 0x8000>;
+ 	};
+ 
+-	wocpu2_ilm: wocpu2_ilm@153E0000 {
+-		compatible = "mediatek,wocpu2_ilm";
+-		reg = <0 0x153E0000 0 0x8000>;
++	wocpu2_ilm: wocpu_ilm@153E0000 {
++                compatible = "mediatek,wocpu_ilm";
++                reg = <0 0x153E0000 0 0x8000>;
++    };
++
++	wocpu0_dlm: wocpu_dlm@151E8000 {
++		compatible = "mediatek,wocpu_dlm";
++		reg = <0 0x151E8000 0 0x2000>;
++
++		resets = <&ethsysrst 0>;
++		reset-names = "wocpu_rst";
++	};
++
++	wocpu1_dlm: wocpu_dlm@0x152E8000 {
++		compatible = "mediatek,wocpu_dlm";
++		reg = <0 0x152E8000 0 0x2000>;
++
++		resets = <&ethsysrst 0>;
++		reset-names = "wocpu_rst";
+ 	};
+ 
+-	wocpu_dlm: wocpu_dlm@151E8000 {
++	wocpu2_dlm: wocpu_dlm@0x153E8000 {
+ 		compatible = "mediatek,wocpu_dlm";
+-		reg = <0 0x151E8000 0 0x2000>,
+-		      <0 0x152E8000 0 0x2000>,
+-		      <0 0x153E8000 0 0x2000>;
++		reg = <0 0x153E8000 0 0x2000>;
+ 
+ 		resets = <&ethsysrst 0>;
+ 		reset-names = "wocpu_rst";
+ 	};
+ 
+-	cpu_boot: wocpu_boot@15194000 {
+-		compatible = "mediatek,wocpu_boot";
+-		reg = <0 0x15194000 0 0x1000>,
+-		      <0 0x15294000 0 0x1000>,
+-		      <0 0x15394000 0 0x1000>;
++	cpu0_boot: wocpu_boot@15194000 {
++		compatible = "mediatek,wocpu0_boot";
++		reg = <0 0x15194000 0 0x1000>;
++	};
++
++	cpu1_boot: wocpu_boot@15294000 {
++		compatible = "mediatek,wocpu1_boot";
++		reg = <0 0x15294000 0 0x1000>;
++	};
++
++	cpu2_boot: wocpu_boot@15394000 {
++		compatible = "mediatek,wocpu2_boot";
++		reg = <0 0x15394000 0 0x1000>;
+ 	};
+ 
+ 	reserved-memory {
+@@ -901,6 +938,7 @@
+ 					 <&topckgen CK_TOP_CB_NET2_D2>;
+ 		mediatek,ethsys = <&ethsys>;
+ 		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++		mediatek,wed = <&wed0>, <&wed1>, <&wed2>;
+ 		mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
+ 		mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
+ 		mediatek,xfi_pll = <&xfi_pll>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+index a22af29..9169188 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+@@ -372,9 +372,23 @@
+ 	status = "okay";
+ };
+ 
+-&wed {
++&wed0 {
+ 	dy_txbm_enable = "true";
+ 	dy_txbm_budge = <8>;
+ 	txbm_init_sz = <10>;
+ 	status = "okay";
+ };
++
++&wed1 {
++	dy_txbm_enable = "true";
++	dy_txbm_budge = <8>;
++	txbm_init_sz = <10>;
++	status = "okay";
++};
++
++&wed2 {
++	dy_txbm_enable = "true";
++	dy_txbm_budge = <8>;
++	txbm_init_sz = <10>;
++	status = "okay";
++};
+\ No newline at end of file
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+index effcfd8..30e4846 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+@@ -382,9 +382,23 @@
+ 	status = "okay";
+ };
+ 
+-&wed {
++&wed0 {
+ 	dy_txbm_enable = "true";
+ 	dy_txbm_budge = <8>;
+ 	txbm_init_sz = <10>;
+ 	status = "okay";
+ };
++
++&wed1 {
++	dy_txbm_enable = "true";
++	dy_txbm_budge = <8>;
++	txbm_init_sz = <10>;
++	status = "okay";
++};
++
++&wed2 {
++	dy_txbm_enable = "true";
++	dy_txbm_budge = <8>;
++	txbm_init_sz = <10>;
++	status = "okay";
++};
+\ No newline at end of file
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+old mode 100755
+new mode 100644
+index 0e9c0bd..ae0acd5
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -9,6 +9,7 @@
+ #include <linux/if_ether.h>
+ #include <linux/if_vlan.h>
+ #include <net/dsa.h>
++#include <net/route.h>
+ #include "mtk_eth_soc.h"
+ #include "mtk_ppe.h"
+ #include "mtk_ppe_regs.h"
+@@ -407,7 +408,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
+ }
+ 
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+-			   int bss, int wcid)
++			   int bss, int wcid, bool amsdu_en)
+ {
+ 	struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
+ 	u32 *ib2 = mtk_foe_entry_ib2(entry);
+@@ -419,6 +420,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+ 
+ 	l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
+ 		    FIELD_PREP(MTK_FOE_WINFO_BSS, bss);
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++	l2->winfo_pao = FIELD_PREP(MTK_FOE_WINFO_PAO_AMSDU_EN, amsdu_en);
++#endif
+ #else
+ 	if (wdma_idx)
+ 		*ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
+@@ -454,6 +458,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
+ 	*ib2 &= ~MTK_FOE_IB2_DSCP;
+ 	*ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
+ 
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++	struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
++
++	if (*ib2 & MTK_FOE_IB2_WDMA_WINFO &&
++	    l2->winfo_pao & MTK_FOE_WINFO_PAO_AMSDU_EN) {
++		u8 tid = (dscp >> 5) & 0xf;
++
++		l2->winfo_pao |= FIELD_PREP(MTK_FOE_WINFO_PAO_TID, tid);
++	}
++#endif
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
+index 2a8b6ef..66c7f10 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
+@@ -428,7 +428,7 @@ int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
+ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
+ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+-			   int bss, int wcid);
++			   int bss, int wcid, bool amsdu_en);
+ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
+ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
+ bool mtk_foe_entry_match(struct mtk_foe_entry *entry, struct mtk_foe_entry *data);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index 95174b7..2d432f2 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -112,6 +112,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
+ 	info->queue = path.mtk_wdma.queue;
+ 	info->bss = path.mtk_wdma.bss;
+ 	info->wcid = path.mtk_wdma.wcid;
++	info->amsdu = path.mtk_wdma.amsdu;
+ 
+ 	return 0;
+ }
+@@ -193,13 +194,15 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
+ 
+ 	if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
+ 		mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
+-				       info.wcid);
++				       info.wcid, info.amsdu);
+ 		pse_port = PSE_PPE0_PORT;
+ #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+ 		if (info.wdma_idx == 0)
+ 			pse_port = PSE_WDMA0_PORT;
+ 		else if (info.wdma_idx == 1)
+ 			pse_port = PSE_WDMA1_PORT;
++		else if (info.wdma_idx == 2)
++			pse_port = PSE_WDMA2_PORT;
+ 		else
+ 			return -EOPNOTSUPP;
+ #endif
+@@ -481,8 +484,6 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ 	if (data.pppoe.num == 1)
+ 		mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
+ 
+-	mtk_foe_entry_set_dscp(&foe, dscp);
+-
+ 	mtk_foe_entry_set_sp(eth->ppe[ppe_index], &foe);
+ 
+ 	err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
+@@ -490,6 +491,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ 	if (err)
+ 		return err;
+ 
++	mtk_foe_entry_set_dscp(&foe, dscp);
++
+ 	if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
+ 		return err;
+ 
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index 68eedd3..2fed493 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -23,9 +23,45 @@
+ #include "mtk_wed_mcu.h"
+ #include "mtk_wed_wo.h"
+ 
+-static struct mtk_wed_hw *hw_list[2];
++#define MTK_WED_AMSDU_BUF_SIZE		(PAGE_SIZE << 4)
++#define MTK_WED_AMSDU_NPAGES		32
++
++static struct mtk_wed_hw *hw_list[3];
+ static DEFINE_MUTEX(hw_lock);
+ 
++static const struct mtk_wed_soc_data mt7622_data = {
++	.regmap = {
++		.tx_bm_tkid		= 0x088,
++		.wpdma_rx_ring0		= 0x770,
++		.reset_idx_tx_mask	= GENMASK(3, 0),
++		.reset_idx_rx_mask	= GENMASK(17, 16),
++	},
++	.tx_ring_desc_size = sizeof(struct mtk_wdma_desc),
++	.wdma_desc_size = sizeof(struct mtk_wdma_desc),
++};
++
++static const struct mtk_wed_soc_data mt7986_data = {
++	.regmap = {
++		.tx_bm_tkid		= 0x0c8,
++		.wpdma_rx_ring0		= 0x770,
++		.reset_idx_tx_mask	= GENMASK(1, 0),
++		.reset_idx_rx_mask	= GENMASK(7, 6),
++	},
++	.tx_ring_desc_size = sizeof(struct mtk_wdma_desc),
++	.wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc),
++};
++
++static const struct mtk_wed_soc_data mt7988_data = {
++	.regmap = {
++		.tx_bm_tkid		= 0x0c8,
++		.wpdma_rx_ring0		= 0x7d0,
++		.reset_idx_tx_mask	= GENMASK(1, 0),
++		.reset_idx_rx_mask	= GENMASK(7, 6),
++	},
++	.tx_ring_desc_size = sizeof(struct mtk_wed_bm_desc),
++	.wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc),
++};
++
+ static void
+ wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val)
+ {
+@@ -74,6 +110,26 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
+ 	return wdma_r32(dev, MTK_WDMA_GLO_CFG);
+ }
+ 
++static u32
++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++	if (wed_r32(dev, reg) & mask)
++		return true;
++
++	return false;
++}
++
++static int
++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++	int sleep = 1000;
++	int timeout = 100 * sleep;
++	u32 val;
++
++	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
++				 timeout, false, dev, reg, mask);
++}
++
+ static int
+ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ {
+@@ -249,7 +305,7 @@ mtk_wed_assign(struct mtk_wed_device *dev)
+ 		if (!hw->wed_dev)
+ 			goto out;
+ 
+-		if (hw->version == 1)
++		if (mtk_wed_is_v1(hw))
+ 			return NULL;
+ 
+ 		/* MT7986 WED devices do not have any pcie slot restrictions */
+@@ -269,40 +325,153 @@ mtk_wed_assign(struct mtk_wed_device *dev)
+ }
+ 
+ static int
+-mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
++mtk_wed_amsdu_buffer_alloc(struct mtk_wed_device *dev)
+ {
+-	struct mtk_wdma_desc *desc;
+-	dma_addr_t desc_phys;
+-	void **page_list;
+-	int token = dev->wlan.token_start;
+-	int ring_size, n_pages, page_idx;
++	struct mtk_wed_hw *hw = dev->hw;
++	struct mtk_wed_amsdu *wed_amsdu;
+ 	int i;
+ 
++	if (!mtk_wed_is_v3_or_greater(hw))
++		return 0;
+ 
+-	if (dev->hw->version == 1)
+-		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
+-	else
+-		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
+-			    MTK_WED_WDMA_RING_SIZE * 2;
++	wed_amsdu = devm_kcalloc(hw->dev, MTK_WED_AMSDU_NPAGES,
++				 sizeof(*wed_amsdu), GFP_KERNEL);
++	if (!wed_amsdu)
++		return -ENOMEM;
++
++	for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
++		void *ptr;
++
++		/* each segment is 64K */
++		ptr = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
++					       __GFP_ZERO | __GFP_COMP |
++					       GFP_DMA32,
++					       get_order(MTK_WED_AMSDU_BUF_SIZE));
++		if (!ptr)
++			goto error;
++
++		wed_amsdu[i].txd = ptr;
++		wed_amsdu[i].txd_phy = dma_map_single(hw->dev, ptr,
++						      MTK_WED_AMSDU_BUF_SIZE,
++						      DMA_TO_DEVICE);
++		if (dma_mapping_error(hw->dev, wed_amsdu[i].txd_phy))
++			goto error;
++	}
++	dev->hw->wed_amsdu = wed_amsdu;
++
++	return 0;
++
++error:
++	for (i--; i >= 0; i--)
++		dma_unmap_single(hw->dev, wed_amsdu[i].txd_phy,
++				 MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
++	return -ENOMEM;
++}
++
++
++static void
++mtk_wed_amsdu_free_buffer(struct mtk_wed_device *dev)
++{
++	struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
++	int i;
++
++	if (!wed_amsdu)
++		return;
++
++	for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
++		dma_unmap_single(dev->hw->dev, wed_amsdu[i].txd_phy,
++				 MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
++		free_pages((unsigned long)wed_amsdu[i].txd,
++			   get_order(MTK_WED_AMSDU_BUF_SIZE));
++	}
++}
++
++static int
++mtk_wed_amsdu_init(struct mtk_wed_device *dev)
++{
++	struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
++	int i, ret;
++
++	if (!wed_amsdu)
++		return 0;
+ 
+-	n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
++	for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++)
++		wed_w32(dev, MTK_WED_AMSDU_HIFTXD_BASE_L(i),
++			wed_amsdu[i].txd_phy);
++
++	/* init all sta parameter */
++	wed_w32(dev, MTK_WED_AMSDU_STA_INFO_INIT, MTK_WED_AMSDU_STA_RMVL |
++		MTK_WED_AMSDU_STA_WTBL_HDRT_MODE |
++		FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_LEN,
++			   dev->wlan.amsdu_max_len >> 8) |
++		FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_NUM,
++			   dev->wlan.amsdu_max_subframes));
++
++	wed_w32(dev, MTK_WED_AMSDU_STA_INFO, MTK_WED_AMSDU_STA_INFO_DO_INIT);
++
++	ret = mtk_wed_poll_busy(dev, MTK_WED_AMSDU_STA_INFO,
++				MTK_WED_AMSDU_STA_INFO_DO_INIT);
++	if (ret) {
++		dev_err(dev->hw->dev, "amsdu initialization failed\n");
++		return ret;
++	}
++
++	/* init partial amsdu offload txd src */
++	wed_set(dev, MTK_WED_AMSDU_HIFTXD_CFG,
++		FIELD_PREP(MTK_WED_AMSDU_HIFTXD_SRC, dev->hw->index));
++
++	/* init qmem */
++	wed_set(dev, MTK_WED_AMSDU_PSE, MTK_WED_AMSDU_PSE_RESET);
++	ret = mtk_wed_poll_busy(dev, MTK_WED_MON_AMSDU_QMEM_STS1, BIT(29));
++	if (ret) {
++		pr_info("%s: amsdu qmem initialization failed\n", __func__);
++		return ret;
++	}
++
++	/* eagle E1 PCIE1 tx ring 22 flow control issue */
++	if (dev->wlan.id == 0x7991)
++		wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING);
++
++	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++
++	return 0;
++}
++
++static int
++mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
++{
++	u32 desc_size = dev->hw->soc->tx_ring_desc_size;
++	int i, page_idx = 0, n_pages, ring_size;
++	int token = dev->wlan.token_start;
++	struct mtk_wed_buf *page_list;
++	dma_addr_t desc_phys;
++	void *desc_ptr;
++
++	if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
++		dev->tx_buf_ring.size = ring_size;
++	} else {
++		dev->tx_buf_ring.size = MTK_WED_TX_BM_DMA_SIZE;
++		ring_size = MTK_WED_TX_BM_PKT_CNT;
++	}
++	n_pages = dev->tx_buf_ring.size / MTK_WED_BUF_PER_PAGE;
+ 
+ 	page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
+ 	if (!page_list)
+ 		return -ENOMEM;
+ 
+-	dev->tx_buf_ring.size = ring_size;
+ 	dev->tx_buf_ring.pages = page_list;
+ 
+-	desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+-				  &desc_phys, GFP_KERNEL);
+-	if (!desc)
++	desc_ptr = dma_alloc_coherent(dev->hw->dev,
++				      dev->tx_buf_ring.size * desc_size,
++				      &desc_phys, GFP_KERNEL);
++	if (!desc_ptr)
+ 		return -ENOMEM;
+ 
+-	dev->tx_buf_ring.desc = desc;
++	dev->tx_buf_ring.desc = desc_ptr;
+ 	dev->tx_buf_ring.desc_phys = desc_phys;
+ 
+-	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
++	for (i = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+ 		dma_addr_t page_phys, buf_phys;
+ 		struct page *page;
+ 		void *buf;
+@@ -319,7 +488,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ 			return -ENOMEM;
+ 		}
+ 
+-		page_list[page_idx++] = page;
++		page_list[page_idx].p = page;
++		page_list[page_idx++].phy_addr = page_phys;
+ 		dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
+ 					DMA_BIDIRECTIONAL);
+ 
+@@ -327,28 +497,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ 		buf_phys = page_phys;
+ 
+ 		for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
+-			u32 txd_size;
+-			u32 ctrl;
+-
+-			txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
++			struct mtk_wdma_desc *desc = desc_ptr;
+ 
+ 			desc->buf0 = cpu_to_le32(buf_phys);
+-			desc->buf1 = cpu_to_le32(buf_phys + txd_size);
+-
+-			if (dev->hw->version == 1)
+-				ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+-				       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
+-						  MTK_WED_BUF_SIZE - txd_size) |
+-				       MTK_WDMA_DESC_CTRL_LAST_SEG1;
+-			else
+-				ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+-				       FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
+-						  MTK_WED_BUF_SIZE - txd_size) |
+-				       MTK_WDMA_DESC_CTRL_LAST_SEG0;
+-			desc->ctrl = cpu_to_le32(ctrl);
+-			desc->info = 0;
+-			desc++;
+-
++			if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++				u32 txd_size, ctrl;
++
++				txd_size = dev->wlan.init_buf(buf, buf_phys,
++							      token++);
++				desc->buf1 = cpu_to_le32(buf_phys + txd_size);
++				ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size);
++				if (mtk_wed_is_v1(dev->hw))
++					ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG1 |
++						FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++							   MTK_WED_BUF_SIZE - txd_size);
++				else
++					ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 |
++						FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
++							   MTK_WED_BUF_SIZE - txd_size);
++				desc->ctrl = cpu_to_le32(ctrl);
++				desc->info = 0;
++			} else {
++				desc->ctrl = cpu_to_le32(token << 16);
++			}
++
++			desc_ptr += desc_size;
+ 			buf += MTK_WED_BUF_SIZE;
+ 			buf_phys += MTK_WED_BUF_SIZE;
+ 		}
+@@ -363,48 +536,107 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
+ {
+-	struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc;
+-	void **page_list = dev->tx_buf_ring.pages;
+-	int ring_size, page_idx;
+-	int i;
++	struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages;
++	struct mtk_wed_hw *hw = dev->hw;
++	int i, page_idx = 0;
+ 
+ 	if (!page_list)
+ 		return;
+ 
+-	if (!desc)
++	if (!dev->tx_buf_ring.desc)
+ 		goto free_pagelist;
+ 
+-	if (dev->hw->version == 1) {
+-		ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
+-	} else {
+-		ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
+-			    MTK_WED_WDMA_RING_SIZE * 2;
+-	}
+-
+-	for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+-		void *page = page_list[page_idx++];
+-		dma_addr_t buf_addr;
++	for (i = 0; i < dev->tx_buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
++		dma_addr_t page_phy = page_list[page_idx].phy_addr;
++		void *page = page_list[page_idx++].p;
+ 
+ 		if (!page)
+ 			break;
+ 
+-		buf_addr = le32_to_cpu(desc[i].buf0);
+-		dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++		dma_unmap_page(dev->hw->dev, page_phy, PAGE_SIZE,
+ 			       DMA_BIDIRECTIONAL);
+ 		__free_page(page);
+ 	}
+ 
+-	dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+-			  desc, dev->tx_buf_ring.desc_phys);
++	dma_free_coherent(dev->hw->dev,
++			  dev->tx_buf_ring.size * hw->soc->tx_ring_desc_size,
++			  dev->tx_buf_ring.desc,
++			  dev->tx_buf_ring.desc_phys);
+ 
+ free_pagelist:
+ 	kfree(page_list);
+ }
+ 
++static int
++mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev)
++{
++	int n_pages = MTK_WED_RX_PG_BM_CNT / MTK_WED_RX_PAGE_BUF_PER_PAGE;
++	struct mtk_wed_buf *page_list;
++	struct mtk_wed_bm_desc *desc;
++	dma_addr_t desc_phys;
++	int i, page_idx = 0;
++
++	if (!dev->wlan.hw_rro)
++		return 0;
++
++	page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
++	if (!page_list)
++		return -ENOMEM;
++
++	dev->hw_rro.size = dev->wlan.rx_nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
++	dev->hw_rro.pages = page_list;
++
++	desc = dma_alloc_coherent(dev->hw->dev,
++				  dev->wlan.rx_nbuf * sizeof(*desc),
++				  &desc_phys, GFP_KERNEL);
++	if (!desc)
++		return -ENOMEM;
++
++	dev->hw_rro.desc = desc;
++	dev->hw_rro.desc_phys = desc_phys;
++
++	for (i = 0, page_idx = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
++		dma_addr_t page_phys, buf_phys;
++		struct page *page;
++		void *buf;
++		int s;
++
++		page = __dev_alloc_pages(GFP_KERNEL, 0);
++		if (!page)
++			return -ENOMEM;
++
++		page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE,
++		                        DMA_BIDIRECTIONAL);
++		if (dma_mapping_error(dev->hw->dev, page_phys)) {
++			__free_page(page);
++			return -ENOMEM;
++		}
++
++		page_list[page_idx].p= page;
++		page_list[page_idx++].phy_addr= page_phys;
++		dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
++		                       DMA_BIDIRECTIONAL);
++
++		buf = page_to_virt(page);
++		buf_phys = page_phys;
++		for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) {
++			desc->buf0 = cpu_to_le32(buf_phys);
++			desc++;
++			buf += MTK_WED_PAGE_BUF_SIZE;
++			buf_phys += MTK_WED_PAGE_BUF_SIZE;
++		}
++
++		dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE,
++					   DMA_BIDIRECTIONAL);
++	}
++
++	return 0;
++}
++
+ static int
+ mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
+ {
+-	struct mtk_rxbm_desc *desc;
++	struct mtk_wed_bm_desc *desc;
+ 	dma_addr_t desc_phys;
+ 
+ 	dev->rx_buf_ring.size = dev->wlan.rx_nbuf;
+@@ -418,13 +650,48 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
+ 	dev->rx_buf_ring.desc_phys = desc_phys;
+ 	dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt);
+ 
+-	return 0;
++	return mtk_wed_hwrro_buffer_alloc(dev);
++}
++
++static void
++mtk_wed_hwrro_free_buffer(struct mtk_wed_device *dev)
++{
++	struct mtk_wed_buf *page_list = dev->hw_rro.pages;
++	struct mtk_wed_bm_desc *desc = dev->hw_rro.desc;
++	int i, page_idx = 0;
++
++	if (!dev->wlan.hw_rro)
++		return;
++
++	if (!page_list)
++		return;
++
++	if (!desc)
++		goto free_pagelist;
++
++	for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
++		dma_addr_t buf_addr = page_list[page_idx].phy_addr;
++		void *page = page_list[page_idx++].p;
++
++		if (!page)
++			break;
++
++		dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++			       DMA_BIDIRECTIONAL);
++		__free_page(page);
++       }
++
++	dma_free_coherent(dev->hw->dev, dev->hw_rro.size * sizeof(*desc),
++                         desc, dev->hw_rro.desc_phys);
++
++free_pagelist:
++       kfree(page_list);
+ }
+ 
+ static void
+ mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
+ {
+-	struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
++	struct mtk_wed_bm_desc *desc = dev->rx_buf_ring.desc;
+ 
+ 	if (!desc)
+ 		return;
+@@ -433,6 +700,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
+ 
+ 	dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc),
+ 			  desc, dev->rx_buf_ring.desc_phys);
++
++	mtk_wed_hwrro_free_buffer(dev);
++}
++
++static void
++mtk_wed_hwrro_init(struct mtk_wed_device *dev)
++{
++	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
++		return;
++
++	wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM,
++		FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128));
++
++	wed_w32(dev, MTK_WED_RRO_PG_BM_BASE, dev->hw_rro.desc_phys);
++
++	wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR,
++		MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX |
++		FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX,
++			   MTK_WED_RX_PG_BM_CNT));
++
++	/* enable rx_page_bm to fetch dmad */
++	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
+ }
+ 
+ static void
+@@ -450,6 +739,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev)
+ 		FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
+ 
+ 	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++
++	mtk_wed_hwrro_init(dev);
+ }
+ 
+ static void
+@@ -465,6 +756,16 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
+ static void
+ mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
+ {
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++)
++		if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
++			mtk_wed_free_ring(dev, &dev->rx_ring[i]);
++
++	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
++		if ((dev->tx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
++			mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
++
+ 	mtk_wed_free_rx_buffer(dev);
+ 	mtk_wed_free_ring(dev, &dev->rro.ring);
+ }
+@@ -475,9 +776,12 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
+-		mtk_wed_free_ring(dev, &dev->tx_ring[i]);
++		if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
++			mtk_wed_free_ring(dev, &dev->tx_ring[i]);
++
+ 	for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
+-		mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
++		if ((dev->rx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
++			mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
+ }
+ 
+ static void
+@@ -485,8 +789,20 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ {
+ 	u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
+ 
+-	if (dev->hw->version == 1)
++	switch (dev->hw->version) {
++	case 1:
+ 		mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
++		break;
++	case 2:
++		mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 |
++			MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 |
++			MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT |
++			MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR;
++		break;
++	case 3:
++		mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
++		break;
++	}
+ 
+ 	if (!dev->hw->num_flows)
+ 		mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
+@@ -498,6 +814,9 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ static void
+ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
+ {
++	if (!mtk_wed_is_v2(dev->hw))
++		return;
++
+ 	if (enable) {
+ 		wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
+ 		wed_w32(dev, MTK_WED_TXP_DW1,
+@@ -509,22 +828,15 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
+ 	}
+ }
+ 
+-#define MTK_WFMDA_RX_DMA_EN	BIT(2)
+-static void
+-mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
++static int
++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev,
++			    struct mtk_wed_ring *ring)
+ {
+-	u32 val;
+ 	int i;
+ 
+-	if(!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED))
+-		return;
+-
+ 	for (i = 0; i < 3; i++) {
+-		u32 cur_idx;
++		u32 cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX);
+ 
+-		cur_idx = wed_r32(dev,
+-				  MTK_WED_WPDMA_RING_RX_DATA(idx) +
+-				  MTK_WED_RING_OFS_CPU_IDX);
+ 		if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
+ 			break;
+ 
+@@ -532,14 +844,12 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
+ 	}
+ 
+ 	if (i == 3) {
+-		dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
+-			       dev->hw->index, idx);
+-		return;
++		dev_err(dev->hw->dev, "mtk_wed%d: dma enable failed!\n",
++			dev->hw->index);
++		return -ETIMEDOUT;
+ 	}
+ 
+-	val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) |
+-	      MTK_WFMDA_RX_DMA_EN;
+-	wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val);
++	return 0;
+ }
+ 
+ static void
+@@ -561,7 +871,7 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+ 		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
+ 		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
+ 		wdma_clr(dev, MTK_WDMA_GLO_CFG,
+ 			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+@@ -573,9 +883,17 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+ 			MTK_WED_WPDMA_RX_D_RX_DRV_EN);
+ 		wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
+ 			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++
++		if (mtk_wed_is_v3_or_greater(dev->hw) &&
++		    mtk_wed_get_rx_capa(dev)) {
++			wdma_clr(dev, MTK_WDMA_PREF_TX_CFG,
++				 MTK_WDMA_PREF_TX_CFG_PREF_EN);
++			wdma_clr(dev, MTK_WDMA_PREF_RX_CFG,
++				 MTK_WDMA_PREF_RX_CFG_PREF_EN);
++		}
+ 	}
+ 
+-	mtk_wed_set_512_support (dev, false);
++	mtk_wed_set_512_support(dev, false);
+ }
+ 
+ static void
+@@ -589,7 +907,7 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+ 	wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
+ 	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+ 
+-	if (dev->hw->version == 1)
++	if (!mtk_wed_get_rx_capa(dev))
+ 		return;
+ 
+ 	wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
+@@ -608,13 +926,21 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
+ 		MTK_WED_CTRL_WED_TX_BM_EN |
+ 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+ 
+-	if (dev->hw->version == 1)
++	if (mtk_wed_is_v1(dev->hw))
+ 		return;
+ 
+ 	wed_clr(dev, MTK_WED_CTRL,
+ 		MTK_WED_CTRL_RX_ROUTE_QM_EN |
+ 		MTK_WED_CTRL_WED_RX_BM_EN |
+ 		MTK_WED_CTRL_RX_RRO_QM_EN);
++
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_AMSDU);
++		wed_clr(dev, MTK_WED_PCIE_INT_CTRL,
++			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
++			MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER);
++	}
+ }
+ 
+ static void
+@@ -627,6 +953,8 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
+ 
+ 	mtk_wdma_rx_reset(dev);
+ 	mtk_wed_reset(dev, MTK_WED_RESET_WED);
++	mtk_wed_amsdu_free_buffer(dev);
++	mtk_wdma_tx_reset(dev);
+ 	mtk_wed_free_tx_buffer(dev);
+ 	mtk_wed_free_tx_rings(dev);
+ 
+@@ -636,7 +964,6 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
+ 		mtk_wed_free_rx_rings(dev);
+ 		if(hw->wed_wo)
+ 			mtk_wed_wo_exit(hw);
+-		mtk_wdma_tx_reset(dev);
+ 	}
+ 
+ 	if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
+@@ -664,21 +991,36 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ 	mutex_unlock(&hw_lock);
+ }
+ 
+-#define PCIE_BASE_ADDR0 0x11280000
+ static void
+ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ {
+ 	switch (dev->wlan.bus_type) {
+ 	case MTK_WED_BUS_PCIE: {
+ 		struct device_node *np = dev->hw->eth->dev->of_node;
+-		struct regmap *regs;
+ 
+-		regs = syscon_regmap_lookup_by_phandle(np,
+-						       "mediatek,wed-pcie");
+-		if (IS_ERR(regs))
+-			break;
++		if (mtk_wed_is_v2(dev->hw)) {
++			struct regmap *regs;
++			regs = syscon_regmap_lookup_by_phandle(np,
++							       "mediatek,wed-pcie");
++			if (IS_ERR(regs))
++				break;
+ 
+-		regmap_update_bits(regs, 0, BIT(0), BIT(0));
++			regmap_update_bits(regs, 0, BIT(0), BIT(0));
++		}
++
++		if (dev->wlan.msi) {
++		     wed_w32(dev, MTK_WED_PCIE_CFG_INTM,
++			     dev->hw->pci_base | 0xc08);
++		     wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++			     dev->hw->pci_base | 0xc04);
++		     wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8));
++		} else {
++		     wed_w32(dev, MTK_WED_PCIE_CFG_INTM,
++			     dev->hw->pci_base | 0x180);
++		     wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++			     dev->hw->pci_base | 0x184);
++		     wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
++		}
+ 
+ 		wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
+ 			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
+@@ -686,19 +1028,9 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ 		/* pcie interrupt control: pola/source selection */
+ 		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+ 			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
+-			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
+-		wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
+-
+-		wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
+-		wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
+-
+-		/* pcie interrupt status trigger register */
+-		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
+-		wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+-
+-		/* pola setting */
+-		wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+-			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
++			MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER |
++			FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL,
++				   dev->hw->index));
+ 		break;
+ 	}
+ 	case MTK_WED_BUS_AXI:
+@@ -714,45 +1046,71 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+ {
+-	if (dev->hw->version == 1) {
+-		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
+-	} else {
+-		mtk_wed_bus_init(dev);
++	int i;
+ 
+-		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_int);
+-		wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK,  dev->wlan.wpdma_mask);
+-		wed_w32(dev, MTK_WED_WPDMA_CFG_TX,  dev->wlan.wpdma_tx);
+-		wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE,  dev->wlan.wpdma_txfree);
+-		wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG,  dev->wlan.wpdma_rx_glo);
+-		wed_w32(dev, MTK_WED_WPDMA_RX_RING,  dev->wlan.wpdma_rx);
++	if (mtk_wed_is_v1(dev->hw)) {
++		wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_phys);
++		return;
+ 	}
++
++	mtk_wed_bus_init(dev);
++
++	wed_w32(dev, MTK_WED_WPDMA_CFG_BASE,  dev->wlan.wpdma_int);
++	wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK,  dev->wlan.wpdma_mask);
++	wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
++	wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE,  dev->wlan.wpdma_txfree);
++
++	if (!mtk_wed_get_rx_capa(dev)) 
++		return;
++
++	wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG,  dev->wlan.wpdma_rx_glo);
++	wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0,  dev->wlan.wpdma_rx[0]);
++
++	if (dev->wlan.wpdma_rx[1])
++		wed_w32(dev, MTK_WED_WPDMA_RX_RING1,  dev->wlan.wpdma_rx[1]);
++
++	if (!dev->wlan.hw_rro)
++		return;
++
++	wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]);
++	wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]);
++	for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++)
++		wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i),
++			dev->wlan.wpdma_rx_pg + i * 0x10);	
+ }
+ 
+ static void
+ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+ {
+-	u32 mask, set;
++	u32 set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2);
++	u32 mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE;
+ 
+ 	mtk_wed_deinit(dev);
+ 	mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ 	mtk_wed_set_wpdma(dev);
+ 
+-	mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
+-	       MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
+-	       MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
+-	set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
+-	      MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
+-	      MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
++	if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++		mask |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
++			MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
++		set |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
++		       MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
++	}
+ 	wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		u32 offset;
++
+ 		offset = dev->hw->index ? 0x04000400 : 0;
++
++		wdma_set(dev, MTK_WDMA_GLO_CFG,
++			 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++			 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES |
++			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
++
+ 		wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
+ 		wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
+ 
+-		wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
+-			MTK_PCIE_BASE(dev->hw->index));
++		wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index));
+ 	} else {
+ 		wed_w32(dev, MTK_WED_WDMA_CFG_BASE, dev->hw->wdma_phy);
+ 		wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_ETH_DMAD_FMT);
+@@ -844,7 +1202,8 @@ mtk_wed_rro_cfg(struct mtk_wed_device *dev)
+ 		},
+ 	};
+ 
+-	return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
++	return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++				    MTK_WED_WO_CMD_WED_CFG,
+ 				    &req, sizeof(req), true);
+ }
+ 
+@@ -895,11 +1254,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
+ 	}
+ 
+ 	/* configure RX_ROUTE_QM */
+-	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
+-	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
+-	wed_set(dev, MTK_WED_RTQM_GLO_CFG,
+-		FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
+-	wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++	if (mtk_wed_is_v2(dev->hw)) {
++		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
++		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
++			FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT,
++				   0x3 + dev->hw->index));
++		wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++	} else {
++		wed_set(dev, MTK_WED_RTQM_ENQ_CFG0,
++			FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT,
++				   0x3 + dev->hw->index));
++	}
+ 
+ 	/* enable RX_ROUTE_QM */
+ 	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
+@@ -918,35 +1284,26 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 
+ 	wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ 			MTK_WED_TX_BM_CTRL_PAUSE |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+ 				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ 				   MTK_WED_TX_RING_SIZE / 256));
+-		wed_w32(dev, MTK_WED_TX_BM_TKID,
+-			FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+-				   dev->wlan.token_start) |
+-			FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+-				   dev->wlan.token_start +
+-				   dev->wlan.nbuf - 1));
+ 		wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+ 			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
+ 			MTK_WED_TX_BM_DYN_THR_HI);
+-	} else {
++	} else if (mtk_wed_is_v2(dev->hw)) {
+ 		wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ 			MTK_WED_TX_BM_CTRL_PAUSE |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+ 				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ 				   dev->tx_buf_ring.size / 128));
+-		wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
+-			FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+-				   dev->wlan.token_start) |
+-			FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+-				   dev->wlan.token_start +
+-				   dev->wlan.nbuf - 1));
++		wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
++			FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
++			MTK_WED_TX_TKID_DYN_THR_HI);
+ 		wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+ 			FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) |
+ 			MTK_WED_TX_BM_DYN_THR_HI_V2);
+@@ -956,32 +1313,73 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ 				   dev->tx_buf_ring.size / 128) |
+ 			FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
+ 				   dev->tx_buf_ring.size / 128));
+-		wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
+-			FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
+-			MTK_WED_TX_TKID_DYN_THR_HI);
+ 	}
+ 
++	wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid,
++		FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++			   dev->wlan.token_start) |
++		FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++			   dev->wlan.token_start + dev->wlan.nbuf - 1));
++
+ 	mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		/* switch to new bm architecture */
++		wed_clr(dev, MTK_WED_TX_BM_CTRL,
++			MTK_WED_TX_BM_CTRL_LEGACY_EN);
++
++		wed_w32(dev, MTK_WED_TX_TKID_CTRL,
++			MTK_WED_TX_TKID_CTRL_PAUSE |
++			FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3,
++				   dev->wlan.nbuf / 128) |
++			FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3,
++				   dev->wlan.nbuf / 128));
++		/* return SKBID + SDP back to bm */
++		wed_set(dev, MTK_WED_TX_TKID_CTRL,
++			MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
++
++		wed_w32(dev, MTK_WED_TX_BM_INIT_PTR,
++			MTK_WED_TX_BM_PKT_CNT |
++			MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
++	}
++
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		wed_set(dev, MTK_WED_CTRL,
+ 			MTK_WED_CTRL_WED_TX_BM_EN |
+ 			MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+-	} else {
+-		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+-		/* rx hw init*/
++	} else if (mtk_wed_get_rx_capa(dev)) {
++		/* rx hw init */
+ 		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+ 			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
+ 			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
+ 
+ 		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
+ 
++		/* reset prefetch index of ring */
++		wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
++			MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++		wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
++			MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++
++		wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
++			MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++		wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
++			MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++
++		/* reset prefetch FIFO of ring */
++		wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG,
++			MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR |
++			MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR);
++		wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0);
++
+ 		mtk_wed_rx_buffer_hw_init(dev);
+ 		mtk_wed_rro_hw_init(dev);
+ 		mtk_wed_route_qm_hw_init(dev);
+ 	}
+ 
+ 	wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
++	if (!mtk_wed_is_v1(dev->hw))
++		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+ }
+ 
+ static void
+@@ -1099,13 +1497,8 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 	if (ret) {
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA);
+ 	} else {
+-		struct mtk_eth *eth = dev->hw->eth;
+-
+-		if(MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+-			wed_set(dev, MTK_WED_RESET_IDX,
+-				MTK_WED_RESET_IDX_RX_V2);
+-		else
+-			wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX);
++		wed_set(dev, MTK_WED_RESET_IDX,
++			dev->hw->soc->regmap.reset_idx_rx_mask);
+ 		wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ 	}
+ 
+@@ -1162,7 +1555,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 	if (busy) {
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA);
+ 	} else {
+-		wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX);
++		wed_w32(dev, MTK_WED_RESET_IDX,
++			dev->hw->soc->regmap.reset_idx_tx_mask);
+ 		wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ 	}
+ 
+@@ -1226,7 +1620,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 	}
+ 
+ 	dev->init_done = false;
+-	if (dev->hw->version == 1)
++	if (mtk_wed_is_v1(dev->hw))
+ 		return;
+ 
+ 	if (!busy) {
+@@ -1257,7 +1651,6 @@ static int
+ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ 			   bool reset)
+ {
+-	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ 	struct mtk_wed_ring *wdma;
+ 
+ 	if (idx >= ARRAY_SIZE(dev->rx_wdma))
+@@ -1265,9 +1658,11 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ 
+ 	wdma = &dev->rx_wdma[idx];
+ 	if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
+-					 desc_size, true))
++					 dev->hw->soc->wdma_desc_size, true))
+ 		return -ENOMEM;
+ 
++	wdma->flags |= MTK_WED_RING_CONFIGURED;
++
+ 	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
+ 		 wdma->desc_phys);
+ 	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT,
+@@ -1286,7 +1681,6 @@ static int
+ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ 			   bool reset)
+ {
+-	u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ 	struct mtk_wed_ring *wdma;
+ 
+ 	if (idx >= ARRAY_SIZE(dev->tx_wdma))
+@@ -1294,9 +1688,29 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ 
+ 	wdma = &dev->tx_wdma[idx];
+ 	if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
+-					 desc_size, true))
++					 dev->hw->soc->wdma_desc_size, true))
+ 		return -ENOMEM;
+ 
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		struct mtk_wdma_desc *desc = wdma->desc;
++		int i;
++
++		for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) {
++			desc->buf0 = 0;
++			desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
++			desc->buf1 = 0;
++			desc->info = MTK_WDMA_TXD0_DESC_INFO_DMA_DONE;
++			desc++;
++			desc->buf0 = 0;
++			desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
++			desc->buf1 = 0;
++			desc->info = MTK_WDMA_TXD1_DESC_INFO_DMA_DONE;
++			desc++;
++		}
++	}
++
++	wdma->flags |= MTK_WED_RING_CONFIGURED;
++
+ 	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
+ 		 wdma->desc_phys);
+ 	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
+@@ -1354,7 +1768,7 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 		MTK_WED_CTRL_WED_TX_BM_EN |
+ 		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
+ 			MTK_WED_PCIE_INT_TRIGGER_STATUS);
+ 
+@@ -1364,8 +1778,9 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 
+ 		wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
+ 	} else {
+-		wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
+-					GENMASK(1, 0));
++		if (mtk_wed_is_v3_or_greater(dev->hw))
++			wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN);
++
+ 		/* initail tx interrupt trigger */
+ 		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
+ 			MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
+@@ -1384,19 +1799,25 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
+ 				    dev->wlan.txfree_tbit));
+ 
+-		wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
+-			MTK_WED_WPDMA_INT_CTRL_RX0_EN |
+-			MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
+-			MTK_WED_WPDMA_INT_CTRL_RX1_EN |
+-			MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
+-			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
+-				   dev->wlan.rx_tbit[0]) |
+-			FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
+-				   dev->wlan.rx_tbit[1]));
++		if (mtk_wed_get_rx_capa(dev)) {
++			wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
++				MTK_WED_WPDMA_INT_CTRL_RX0_EN |
++				MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
++				MTK_WED_WPDMA_INT_CTRL_RX1_EN |
++				MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
++				FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
++					   dev->wlan.rx_tbit[0]) |
++				FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
++					   dev->wlan.rx_tbit[1]));
++
++			wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
++						GENMASK(1, 0));
++		}
+ 
+ 		wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
+ 		wed_set(dev, MTK_WED_WDMA_INT_CTRL,
+-			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
++			FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,
++				   dev->wdma_idx));
+ 	}
+ 	/* initail wdma interrupt agent */
+ 	wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
+@@ -1407,56 +1828,293 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ 	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
+ }
+ 
++#define MTK_WFMDA_RX_DMA_EN 	BIT(2)
+ static void
+ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ {
+-	wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
+-		MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
++	int i;
++
++	if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++		wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
++			MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
++		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++			MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
++		wdma_set(dev, MTK_WDMA_GLO_CFG,
++			 MTK_WDMA_GLO_CFG_TX_DMA_EN |
++			 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++			 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
++		wed_set(dev, MTK_WED_WPDMA_CTRL, MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++	} else {
++		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++			MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN |
++			MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR);
++		wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
++	}
+ 
+ 	wed_set(dev, MTK_WED_GLO_CFG,
+ 		MTK_WED_GLO_CFG_TX_DMA_EN |
+ 		MTK_WED_GLO_CFG_RX_DMA_EN);
+-	wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+-		MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
+-		MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
++
+ 	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+ 		MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
+ 
+-	wdma_set(dev, MTK_WDMA_GLO_CFG,
+-		 MTK_WDMA_GLO_CFG_TX_DMA_EN |
+-		 MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
+-		 MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
+-
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		wdma_set(dev, MTK_WDMA_GLO_CFG,
+ 			 MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+-	} else {
+-		int i;
++		return;
++	}
+ 
+-		wed_set(dev, MTK_WED_WPDMA_CTRL,
+-			MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++	wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++		MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
++		MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+ 
+-		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+-			MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
+-			MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++			FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) |
++			FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8));
++		wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++			MTK_WED_WDMA_RX_PREF_DDONE2_EN);
++		wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
+ 
++		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
++			MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST);
+ 		wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+-			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
+-			MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++			MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK |
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK |
++			MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
+ 
+-		wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+-			MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
+-			MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++		wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++		wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++	}
+ 
+-		wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
+-			MTK_WED_WPDMA_RX_D_RX_DRV_EN |
+-			FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
+-			FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
+-				   0x2));
++	wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
++		MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
++		MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++
++	if (!mtk_wed_get_rx_capa(dev))
++		return;
++
++	wed_set(dev, MTK_WED_WDMA_GLO_CFG,
++		MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
++		MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++
++	wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN);
++	wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++		MTK_WED_WPDMA_RX_D_RX_DRV_EN |
++		FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
++		FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, 0x2));
++
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++			MTK_WED_WPDMA_RX_D_PREF_EN |
++			FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) |
++			FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8));
++
++		wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
++		wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++		wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++	}
++
++	for (i = 0; i < MTK_WED_RX_QUEUES; i++) {
++		struct mtk_wed_ring *ring = &dev->rx_ring[i];
++		u32 val;
++
++		if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++			continue;
++
++		if(mtk_wed_check_wfdma_rx_fill(dev, ring)) {
++			dev_err(dev->hw->dev,
++				"mtk_wed%d: rx(%d) dma enable failed!\n",
++				dev->hw->index, i);
++			continue;
++		}
++
++		val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
++				dev->wlan.phy_base) | MTK_WFMDA_RX_DMA_EN;
++
++		wifi_w32(dev,
++			 dev->wlan.wpdma_rx_glo - dev->wlan.phy_base,
++			 val);
++
++		dev_err(dev->hw->dev,
++			"mtk_wed%d: rx(%d) dma enable successful!\n",
++			dev->hw->index, i);
++	}
++}
++
++static void
++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
++{
++	int i;
++
++	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
++	wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
++
++	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
++		return;
++
++	wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
++	wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++		MTK_WED_RRO_MSDU_PG_DRV_CLR);
++
++	wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX,
++		MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN |
++		MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR |
++		MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN |
++		MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR |
++		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG,
++			   dev->wlan.rro_rx_tbit[0]) |
++		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG,
++			   dev->wlan.rro_rx_tbit[1]));
++
++	wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG,
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN |
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR |
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN |
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR |
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN |
++		MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR |
++		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG,
++			   dev->wlan.rx_pg_tbit[0]) |
++		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG,
++			   dev->wlan.rx_pg_tbit[1])|
++		FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG,
++			   dev->wlan.rx_pg_tbit[2]));
++
++	/*
++	 * RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after
++	 * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken
++	 */
++	wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++		MTK_WED_RRO_MSDU_PG_DRV_EN);
++
++	for (i = 0; i < MTK_WED_RX_QUEUES; i++) {
++		struct mtk_wed_ring *ring = &dev->rx_rro_ring[i];
++
++		if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++			continue;
++
++		if (mtk_wed_check_wfdma_rx_fill(dev, ring))
++			dev_err(dev->hw->dev,
++				"mtk_wed%d: rx_rro_ring(%d) init failed!\n",
++				dev->hw->index, i);
++	}
++
++	for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++){
++		struct mtk_wed_ring *ring = &dev->rx_page_ring[i];
++
++		if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++			continue;
++
++		if (mtk_wed_check_wfdma_rx_fill(dev, ring))
++			dev_err(dev->hw->dev,
++				"mtk_wed%d: rx_page_ring(%d) init failed!\n",
++				dev->hw->index, i);
++	}
++}
++
++static void
++mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
++{
++	struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
++
++	ring->wpdma = regs;
++
++	wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE,
++		readl(regs));
++	wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT,
++		readl(regs + MTK_WED_RING_OFS_COUNT));
++
++	ring->flags |= MTK_WED_RING_CONFIGURED;
++}
++
++static void
++mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
++{
++	struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
++
++	ring->wpdma = regs;
++
++	wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE,
++		readl(regs));
++	wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT,
++		readl(regs + MTK_WED_RING_OFS_COUNT));
++
++	ring->flags |= MTK_WED_RING_CONFIGURED;
++}
++
++static int
++mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
++{
++	struct mtk_wed_ring *ring = &dev->ind_cmd_ring;
++	u32 val = readl(regs + MTK_WED_RING_OFS_COUNT);
++	int i = 0, count = 0;
+ 
+-		for (i = 0; i < MTK_WED_RX_QUEUES; i++)
+-			mtk_wed_check_wfdma_rx_fill(dev, i);
++	ring->wpdma = regs;
++
++	if (readl(regs) & 0xf)
++		pr_info("%s(): address is not 16-byte alignment\n", __func__);
++
++	wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE,
++		readl(regs) & 0xfffffff0);
++
++	wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT,
++		readl(regs + MTK_WED_RING_OFS_COUNT));
++
++	/* ack sn cr */
++	wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base +
++		dev->wlan.ind_cmd.ack_sn_addr);
++	wed_w32(dev, MTK_WED_RRO_CFG1,
++		FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ,
++			   dev->wlan.ind_cmd.win_size) |
++		FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID,
++			   dev->wlan.ind_cmd.particular_sid));
++
++	/* particular session addr element */
++	wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0,
++		dev->wlan.ind_cmd.particular_se_phys);
++
++	for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) {
++		wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA,
++			dev->wlan.ind_cmd.addr_elem_phys[i] >> 4);
++		wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
++			MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f));
++
++		val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
++		while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) && count++ < 100)
++			val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
++
++		if (count >= 100)
++			dev_err(dev->hw->dev,
++				"mtk_wed%d: write ba session base failed!\n",
++				dev->hw->index);
+ 	}
++
++	/* pn check init */
++	for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) {
++		wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M,
++			MTK_WED_PN_CHECK_IS_FIRST);
++
++		wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR |
++			FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i));
++
++		count = 0;
++		val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
++		while (!(val & MTK_WED_PN_CHECK_WR_RDY) && count++ < 100)
++			val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
++
++		if (count >= 100)
++			dev_err(dev->hw->dev,
++				"mtk_wed%d: session(%d) init failed!\n",
++				dev->hw->index, i);
++	}
++
++	wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN);
++	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
++
++	return 0;
+ }
+ 
+ static void
+@@ -1477,14 +2135,14 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 
+ 	mtk_wed_set_ext_int(dev, true);
+ 
+-	if (dev->hw->version == 1) {
++	if (mtk_wed_is_v1(dev->hw)) {
+ 		u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
+ 			  FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID,
+ 				     dev->hw->index);
+ 
+ 		val |= BIT(0) | (BIT(1) * !!dev->hw->index);
+ 		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
+-	} else {
++	} else if (mtk_wed_get_rx_capa(dev)) {
+ 		/* driver set mid ready and only once */
+ 		wed_w32(dev, MTK_WED_EXT_INT_MASK1,
+ 			MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
+@@ -1494,12 +2152,19 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 		wed_r32(dev, MTK_WED_EXT_INT_MASK1);
+ 		wed_r32(dev, MTK_WED_EXT_INT_MASK2);
+ 
++		if (mtk_wed_is_v3_or_greater(dev->hw)) {
++			wed_w32(dev, MTK_WED_EXT_INT_MASK3,
++				MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
++			wed_r32(dev, MTK_WED_EXT_INT_MASK3);
++		}
++
+ 		if (mtk_wed_rro_cfg(dev))
+ 			return;
+ 
+ 	}
+ 
+ 	mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
++	mtk_wed_amsdu_init(dev);
+ 
+ 	mtk_wed_dma_enable(dev);
+ 	dev->running = true;
+@@ -1537,11 +2202,13 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 				       : &dev->wlan.platform_dev->dev;
+ 	dev_info(device, "attaching wed device %d version %d\n",
+ 		 hw->index, hw->version);
++
+ 	dev->hw = hw;
+ 	dev->dev = hw->dev;
+ 	dev->irq = hw->irq;
+ 	dev->wdma_idx = hw->index;
+ 	dev->version = hw->version;
++	dev->hw->pci_base = mtk_wed_get_pci_base(dev);
+ 
+ 	if (hw->eth->dma_dev == hw->eth->dev &&
+ 	    of_dma_is_coherent(hw->eth->dev->of_node))
+@@ -1551,6 +2218,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	if (ret)
+ 		goto out;
+ 
++	ret = mtk_wed_amsdu_buffer_alloc(dev);
++	if (ret)
++		goto out;
++
+ 	if (mtk_wed_get_rx_capa(dev)) {
+ 		ret = mtk_wed_rro_alloc(dev);
+ 		if (ret)
+@@ -1563,13 +2234,14 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	init_completion(&dev->wlan_reset_done);
+ 	atomic_set(&dev->fe_reset, 0);
+ 
+-	if (hw->version == 1) {
++	if (mtk_wed_is_v1(hw))
+ 		regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ 				   BIT(hw->index), 0);
+-	} else {
++	else
+ 		dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
++
++	if (mtk_wed_get_rx_capa(dev))
+ 		ret = mtk_wed_wo_init(hw);
+-	}
+ 
+ out:
+ 	if (ret) {
+@@ -1613,6 +2285,24 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
+ 
+ 	ring->reg_base = MTK_WED_RING_TX(idx);
+ 	ring->wpdma = regs;
++	ring->flags |= MTK_WED_RING_CONFIGURED;
++
++	if (mtk_wed_is_v3_or_greater(dev->hw) && idx == 1) {
++		/* reset prefetch index */
++		wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++		       MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++		       MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++		wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++		       MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++		       MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++		/* reset prefetch FIFO */
++		wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
++		       MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
++		       MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
++		wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
++	}
+ 
+ 	/* WED -> WPDMA */
+ 	wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
+@@ -1632,7 +2322,7 @@ static int
+ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+ {
+ 	struct mtk_wed_ring *ring = &dev->txfree_ring;
+-	int i, index = dev->hw->version == 1;
++	int i, index = mtk_wed_is_v1(dev->hw);
+ 
+ 	/*
+ 	 * For txfree event handling, the same DMA ring is shared between WED
+@@ -1692,9 +2382,13 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
+ 
+ 	val = wed_r32(dev, MTK_WED_EXT_INT_STATUS);
+ 	wed_w32(dev, MTK_WED_EXT_INT_STATUS, val);
+-	val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
+-	if (!dev->hw->num_flows)
+-		val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		val &= MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
++	} else {
++		val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
++		if (!dev->hw->num_flows)
++			val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
++	}
+ 	if (val && net_ratelimit())
+ 		pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val);
+ 
+@@ -1718,19 +2412,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask)
+ int mtk_wed_flow_add(int index)
+ {
+ 	struct mtk_wed_hw *hw = hw_list[index];
+-	int ret;
++	int ret = 0;
+ 
+-	if (!hw || !hw->wed_dev)
+-		return -ENODEV;
++	mutex_lock(&hw_lock);
+ 
+-	if (hw->num_flows) {
+-		hw->num_flows++;
+-		return 0;
++	if (!hw || !hw->wed_dev) {
++		ret = -ENODEV;
++		goto out;
+ 	}
+ 
+-	mutex_lock(&hw_lock);
+-	if (!hw->wed_dev) {
+-		ret = -ENODEV;
++	if (!hw->wed_dev->wlan.offload_enable)
++		goto out;
++
++	if (hw->num_flows) {
++		hw->num_flows++;
+ 		goto out;
+ 	}
+ 
+@@ -1749,14 +2444,15 @@ void mtk_wed_flow_remove(int index)
+ {
+ 	struct mtk_wed_hw *hw = hw_list[index];
+ 
+-	if (!hw)
+-		return;
++	mutex_lock(&hw_lock);
+ 
+-	if (--hw->num_flows)
+-		return;
++	if (!hw || !hw->wed_dev)
++		goto out;
+ 
+-	mutex_lock(&hw_lock);
+-	if (!hw->wed_dev)
++	if (!hw->wed_dev->wlan.offload_disable)
++		goto out;
++
++	if (--hw->num_flows)
+ 		goto out;
+ 
+ 	hw->wed_dev->wlan.offload_disable(hw->wed_dev);
+@@ -1799,6 +2495,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 		.detach = mtk_wed_detach,
+ 		.setup_tc = mtk_wed_eth_setup_tc,
+ 		.ppe_check = mtk_wed_ppe_check,
++		.start_hw_rro = mtk_wed_start_hw_rro,
++		.rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup,
++		.msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup,
++		.ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup,
+ 	};
+ 	struct device_node *eth_np = eth->dev->of_node;
+ 	struct platform_device *pdev;
+@@ -1840,14 +2540,22 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 	hw->wdma_phy = wdma_phy;
+ 	hw->index = index;
+ 	hw->irq = irq;
+-	hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
++	hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) ?
++		      3 : MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
+ 
+-	if (hw->version == 1) {
++	switch (hw->version) {
++	case 2:
++		hw->soc = &mt7986_data;
++		break;
++	case 3:
++		hw->soc = &mt7988_data;
++		break;
++	default:
++	case 1:
+ 		hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
+-							     "mediatek,pcie-mirror");
++				"mediatek,pcie-mirror");
+ 		hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
+-							     "mediatek,hifsys");
+-
++				"mediatek,hifsys");
+ 		if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) {
+ 			kfree(hw);
+ 			goto unlock;
+@@ -1857,8 +2565,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 			regmap_write(hw->mirror, 0, 0);
+ 			regmap_write(hw->mirror, 4, 0);
+ 		}
++		hw->soc = &mt7622_data;
++		break;
+ 	}
+-
++		
+ 	mtk_wed_hw_add_debugfs(hw);
+ 
+ 	hw_list[index] = hw;
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
+index 2ce1a5b..f5e30ce 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed.h
+@@ -8,12 +8,18 @@
+ #include <linux/debugfs.h>
+ #include <linux/regmap.h>
+ #include <linux/netdevice.h>
++
++#include "mtk_wed_regs.h"
++
+ #define MTK_PCIE_BASE(n)		(0x1a143000 + (n) * 0x2000)
+ 
+-#define MTK_WED_PKT_SIZE		1900
++#define MTK_WED_PKT_SIZE		1920//1900
+ #define MTK_WED_BUF_SIZE		2048
++#define MTK_WED_PAGE_BUF_SIZE		128
+ #define MTK_WED_BUF_PER_PAGE		(PAGE_SIZE / 2048)
++#define MTK_WED_RX_PAGE_BUF_PER_PAGE	(PAGE_SIZE / 128)
+ #define MTK_WED_RX_RING_SIZE		1536
++#define MTK_WED_RX_PG_BM_CNT		8192
+ 
+ #define MTK_WED_TX_RING_SIZE		2048
+ #define MTK_WED_WDMA_RING_SIZE		512
+@@ -27,12 +33,27 @@
+ #define MTK_WED_RRO_QUE_CNT		8192
+ #define MTK_WED_MIOD_ENTRY_CNT		128
+ 
++#define MTK_WED_TX_BM_DMA_SIZE		65536
++#define MTK_WED_TX_BM_PKT_CNT		32768
++
+ #define MTK_WED_MODULE_ID_WO		1
+ 
+ struct mtk_eth;
+ struct mtk_wed_wo;
+ 
++struct mtk_wed_soc_data {
++	struct {
++		u32 tx_bm_tkid;
++		u32 wpdma_rx_ring0;
++		u32 reset_idx_tx_mask;
++		u32 reset_idx_rx_mask;
++	} regmap;
++	u32 tx_ring_desc_size;
++	u32 wdma_desc_size;
++};
++
+ struct mtk_wed_hw {
++	const struct mtk_wed_soc_data *soc;
+ 	struct device_node *node;
+ 	struct mtk_eth *eth;
+ 	struct regmap *regs;
+@@ -44,12 +65,15 @@ struct mtk_wed_hw {
+ 	struct dentry *debugfs_dir;
+ 	struct mtk_wed_device *wed_dev;
+ 	struct mtk_wed_wo *wed_wo;
++	struct mtk_wed_amsdu *wed_amsdu;
++	u32 pci_base;
+ 	u32 debugfs_reg;
+ 	u32 num_flows;
+ 	u8 version;
+ 	char dirname[5];
+ 	int irq;
+ 	int index;
++	int token_id;
+ };
+ 
+ struct mtk_wdma_info {
+@@ -57,9 +81,41 @@ struct mtk_wdma_info {
+ 	u8 queue;
+ 	u16 wcid;
+ 	u8 bss;
++	u32 usr_info;
++	u8 tid;
++	u8 is_fixedrate;
++	u8 is_prior;
++	u8 is_sp;
++	u8 hf;
++	u8 amsdu;
++};
++
++struct mtk_wed_amsdu {
++	void *txd;
++	dma_addr_t txd_phy;
+ };
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static inline bool mtk_wed_is_v1(struct mtk_wed_hw *hw)
++{
++	return hw->version == 1;
++}
++
++static inline bool mtk_wed_is_v2(struct mtk_wed_hw *hw)
++{
++	return hw->version == 2;
++}
++
++static inline bool mtk_wed_is_v3(struct mtk_wed_hw *hw)
++{
++	return hw->version == 3;
++}
++
++static inline bool mtk_wed_is_v3_or_greater(struct mtk_wed_hw *hw)
++{
++	return hw->version > 2;
++}
++
+ static inline void
+ wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+ {
+@@ -154,6 +210,21 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+ 	writel(val, dev->txfree_ring.wpdma + reg);
+ }
+ 
++static inline u32 mtk_wed_get_pci_base(struct mtk_wed_device *dev)
++{
++	if (!mtk_wed_is_v3_or_greater(dev->hw))
++		return MTK_WED_PCIE_BASE;
++
++	switch (dev->hw->index) {
++	case 1:
++		return MTK_WED_PCIE_BASE1;
++	case 2:
++		return MTK_WED_PCIE_BASE2;
++	default:
++		return MTK_WED_PCIE_BASE0;
++	}
++}
++
+ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 		    void __iomem *wdma, phys_addr_t wdma_phy,
+ 		    int index);
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+index 7d8be99..69fe29b 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+@@ -11,9 +11,11 @@ struct reg_dump {
+ 	u16 offset;
+ 	u8 type;
+ 	u8 base;
++	u32 mask;
+ };
+ 
+ enum {
++	DUMP_TYPE_END,
+ 	DUMP_TYPE_STRING,
+ 	DUMP_TYPE_WED,
+ 	DUMP_TYPE_WDMA,
+@@ -23,8 +25,11 @@ enum {
+ 	DUMP_TYPE_WED_RRO,
+ };
+ 
++#define DUMP_END() { .type = DUMP_TYPE_END }
+ #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
+ #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
++#define DUMP_REG_MASK(_reg, _mask) { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask }
++
+ #define DUMP_RING(_prefix, _base, ...)				\
+ 	{ _prefix " BASE", _base, __VA_ARGS__ },		\
+ 	{ _prefix " CNT",  _base + 0x4, __VA_ARGS__ },	\
+@@ -32,6 +37,7 @@ enum {
+ 	{ _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
+ 
+ #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
++#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask)
+ #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
+ 
+ #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
+@@ -52,36 +58,49 @@ print_reg_val(struct seq_file *s, const char *name, u32 val)
+ 
+ static void
+ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
+-	      const struct reg_dump *regs, int n_regs)
++	      const struct reg_dump **regs)
+ {
+-	const struct reg_dump *cur;
++	const struct reg_dump **cur_o = regs, *cur;
++	bool newline = false;
+ 	u32 val;
+ 
+-	for (cur = regs; cur < &regs[n_regs]; cur++) {
+-		switch (cur->type) {
+-		case DUMP_TYPE_STRING:
+-			seq_printf(s, "%s======== %s:\n",
+-				   cur > regs ? "\n" : "",
+-				   cur->name);
+-			continue;
+-		case DUMP_TYPE_WED:
+-		case DUMP_TYPE_WED_RRO:
+-			val = wed_r32(dev, cur->offset);
+-			break;
+-		case DUMP_TYPE_WDMA:
+-			val = wdma_r32(dev, cur->offset);
+-			break;
+-		case DUMP_TYPE_WPDMA_TX:
+-			val = wpdma_tx_r32(dev, cur->base, cur->offset);
+-			break;
+-		case DUMP_TYPE_WPDMA_TXFREE:
+-			val = wpdma_txfree_r32(dev, cur->offset);
+-			break;
+-		case DUMP_TYPE_WPDMA_RX:
+-			val = wpdma_rx_r32(dev, cur->base, cur->offset);
+-			break;
++	while (*cur_o) {
++		cur = *cur_o;
++
++		while (cur->type != DUMP_TYPE_END) {
++			switch (cur->type) {
++			case DUMP_TYPE_STRING:
++				seq_printf(s, "%s======== %s:\n",
++					   newline ? "\n" : "",
++					   cur->name);
++				newline = true;
++				cur++;
++				continue;
++			case DUMP_TYPE_WED:
++			case DUMP_TYPE_WED_RRO:
++				val = wed_r32(dev, cur->offset);
++				break;
++			case DUMP_TYPE_WDMA:
++				val = wdma_r32(dev, cur->offset);
++				break;
++			case DUMP_TYPE_WPDMA_TX:
++				val = wpdma_tx_r32(dev, cur->base, cur->offset);
++				break;
++			case DUMP_TYPE_WPDMA_TXFREE:
++				val = wpdma_txfree_r32(dev, cur->offset);
++				break;
++			case DUMP_TYPE_WPDMA_RX:
++				val = wpdma_rx_r32(dev, cur->base, cur->offset);
++				break;
++			}
++
++			if (cur->mask)
++				val = (cur->mask & val) >> (ffs(cur->mask) - 1);
++
++			print_reg_val(s, cur->name, val);
++			cur++;
+ 		}
+-		print_reg_val(s, cur->name, val);
++		cur_o++;
+ 	}
+ }
+ 
+@@ -89,7 +108,7 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
+ static int
+ wed_txinfo_show(struct seq_file *s, void *data)
+ {
+-	static const struct reg_dump regs[] = {
++	static const struct reg_dump regs_common[] = {
+ 		DUMP_STR("WED TX"),
+ 		DUMP_WED(WED_TX_MIB(0)),
+ 		DUMP_WED_RING(WED_RING_TX(0)),
+@@ -128,16 +147,32 @@ wed_txinfo_show(struct seq_file *s, void *data)
+ 		DUMP_WDMA_RING(WDMA_RING_RX(0)),
+ 		DUMP_WDMA_RING(WDMA_RING_RX(1)),
+ 
+-		DUMP_STR("TX FREE"),
++		DUMP_STR("WED TX FREE"),
+ 		DUMP_WED(WED_RX_MIB(0)),
++		DUMP_WED_RING(WED_RING_RX(0)),
++		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)),
++
++		DUMP_WED(WED_RX_MIB(1)),
++		DUMP_WED_RING(WED_RING_RX(1)),
++		DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)),
++		DUMP_STR("WED_WPDMA TX FREE"),
++		DUMP_WED_RING(WED_WPDMA_RING_RX(0)),
++		DUMP_WED_RING(WED_WPDMA_RING_RX(1)),
++		DUMP_END(),
++	};
++
++	static const struct reg_dump *regs[] = {
++		&regs_common[0],
++		NULL,
+ 	};
++
+ 	struct mtk_wed_hw *hw = s->private;
+ 	struct mtk_wed_device *dev = hw->wed_dev;
+ 
+ 	if (!dev)
+ 		return 0;
+ 
+-	dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
++	dump_wed_regs(s, dev, regs);
+ 
+ 	return 0;
+ }
+@@ -146,7 +181,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
+ static int
+ wed_rxinfo_show(struct seq_file *s, void *data)
+ {
+-	static const struct reg_dump regs[] = {
++	static const struct reg_dump regs_common[] = {
+ 		DUMP_STR("WPDMA RX"),
+ 		DUMP_WPDMA_RX_RING(0),
+ 		DUMP_WPDMA_RX_RING(1),
+@@ -164,7 +199,7 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ 		DUMP_WED_RING(WED_RING_RX_DATA(0)),
+ 		DUMP_WED_RING(WED_RING_RX_DATA(1)),
+ 
+-		DUMP_STR("WED RRO"),
++		DUMP_STR("WED WO RRO"),
+ 		DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
+ 		DUMP_WED(WED_RROQM_MID_MIB),
+ 		DUMP_WED(WED_RROQM_MOD_MIB),
+@@ -175,16 +210,6 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ 		DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
+ 		DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
+ 
+-		DUMP_STR("WED Route QM"),
+-		DUMP_WED(WED_RTQM_R2H_MIB(0)),
+-		DUMP_WED(WED_RTQM_R2Q_MIB(0)),
+-		DUMP_WED(WED_RTQM_Q2H_MIB(0)),
+-		DUMP_WED(WED_RTQM_R2H_MIB(1)),
+-		DUMP_WED(WED_RTQM_R2Q_MIB(1)),
+-		DUMP_WED(WED_RTQM_Q2H_MIB(1)),
+-		DUMP_WED(WED_RTQM_Q2N_MIB),
+-		DUMP_WED(WED_RTQM_Q2B_MIB),
+-		DUMP_WED(WED_RTQM_PFDBK_MIB),
+ 
+ 		DUMP_STR("WED WDMA TX"),
+ 		DUMP_WED(WED_WDMA_TX_MIB),
+@@ -205,15 +230,99 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ 		DUMP_WED(WED_RX_BM_INTF2),
+ 		DUMP_WED(WED_RX_BM_INTF),
+ 		DUMP_WED(WED_RX_BM_ERR_STS),
++		DUMP_END()
++	};
++
++	static const struct reg_dump regs_v2[] = {
++		DUMP_STR("WED Route QM"),
++		DUMP_WED(WED_RTQM_R2H_MIB(0)),
++		DUMP_WED(WED_RTQM_R2Q_MIB(0)),
++		DUMP_WED(WED_RTQM_Q2H_MIB(0)),
++		DUMP_WED(WED_RTQM_R2H_MIB(1)),
++		DUMP_WED(WED_RTQM_R2Q_MIB(1)),
++		DUMP_WED(WED_RTQM_Q2H_MIB(1)),
++		DUMP_WED(WED_RTQM_Q2N_MIB),
++		DUMP_WED(WED_RTQM_Q2B_MIB),
++		DUMP_WED(WED_RTQM_PFDBK_MIB),
++
++		DUMP_END()
++	};
++
++	static const struct reg_dump regs_v3[] = {
++		DUMP_STR("WED RX RRO DATA"),
++		DUMP_WED_RING(WED_RRO_RX_D_RX(0)),
++		DUMP_WED_RING(WED_RRO_RX_D_RX(1)),
++
++		DUMP_STR("WED RX MSDU PAGE"),
++		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)),
++		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)),
++		DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)),
++
++		DUMP_STR("WED RX IND CMD"),
++		DUMP_WED(WED_IND_CMD_RX_CTRL1),
++		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT),
++		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX),
++		DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX),
++		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT),
++		DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT),
++		DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0,
++			      WED_IND_CMD_PREFETCH_FREE_CNT),
++		DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID),
++
++		DUMP_STR("WED ADDR ELEM"),
++		DUMP_WED(WED_ADDR_ELEM_CFG0),
++		DUMP_WED_MASK(WED_ADDR_ELEM_CFG1,
++			      WED_ADDR_ELEM_PREFETCH_FREE_CNT),
++
++		DUMP_STR("WED Route QM"),
++		DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT),
++		DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT),
++		DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT),
++		DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT),
++		DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT),
++		DUMP_WED(WED_RTQM_ENQ_ERR_CNT),
++
++		DUMP_WED(WED_RTQM_DEQ_DMAD_CNT),
++		DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT),
++		DUMP_WED(WED_RTQM_DEQ_PKT_CNT),
++		DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT),
++		DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT),
++		DUMP_WED(WED_RTQM_DEQ_ERR_CNT),
++
++		DUMP_END()
++	};
++
++	static const struct reg_dump *regs_new_v2[] = {
++		&regs_common[0],
++		&regs_v2[0],
++		NULL,
++	};
++
++	static const struct reg_dump *regs_new_v3[] = {
++		&regs_common[0],
++		&regs_v3[0],
++		NULL,
+ 	};
+ 
+ 	struct mtk_wed_hw *hw = s->private;
+ 	struct mtk_wed_device *dev = hw->wed_dev;
++	const struct reg_dump **regs;
+ 
+ 	if (!dev)
+ 		return 0;
+ 
+-	dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
++	switch(dev->hw->version) {
++	case 2:
++		regs = regs_new_v2;
++		break;
++	case 3:
++		regs = regs_new_v3;
++		break;
++	default:
++		return 0;
++	}
++
++	dump_wed_regs(s, dev, regs);
+ 
+ 	return 0;
+ }
+@@ -248,6 +357,381 @@ mtk_wed_reg_get(void *data, u64 *val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
+              "0x%08llx\n");
+ 
++static int
++wed_token_txd_show(struct seq_file *s, void *data)
++{
++	struct mtk_wed_hw *hw = s->private;
++	struct mtk_wed_device *dev = hw->wed_dev;
++	struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages;
++	int token = dev->wlan.token_start;
++	u32 val = hw->token_id, size = 1;
++	int page_idx = (val - token) / 2;
++	int i;
++
++	if (val < token) {
++		size = val;
++		page_idx = 0;
++	}
++
++	for (i = 0; i < size; i += MTK_WED_BUF_PER_PAGE) {
++		void *page = page_list[page_idx++].p;
++		void *buf;
++		int j;
++
++		if (!page)
++			break;
++
++		buf = page_to_virt(page);
++
++		for (j = 0; j < MTK_WED_BUF_PER_PAGE; j++) {
++			printk("[TXD]:token id = %d\n", token + 2 * (page_idx - 1) + j);
++			print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, (u8 *)buf, 128, false);
++			seq_printf(s, "\n");
++
++			buf += MTK_WED_BUF_SIZE;
++		}
++	}
++
++	return 0;
++}
++
++DEFINE_SHOW_ATTRIBUTE(wed_token_txd);
++
++static int
++wed_amsdu_show(struct seq_file *s, void *data)
++{
++	static const struct reg_dump regs_common[] = {
++		DUMP_STR("WED AMDSU INFO"),
++		DUMP_WED(WED_MON_AMSDU_FIFO_DMAD),
++
++		DUMP_STR("WED AMDSU ENG0 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(0)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(0)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(0)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(0)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(0)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG1 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(1)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(1)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(1)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(1)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(1)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG2 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(2)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(2)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(2)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(2)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(2)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG3 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(3)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(3)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(3)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(3)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(3)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG4 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(4)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(4)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(4)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(4)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(4)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG5 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(5)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(5)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(5)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(5)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(5)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG6 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(6)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(6)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(6)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(6)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(6)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG7 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(7)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(7)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(7)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(7)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(7)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED AMDSU ENG8 INFO"),
++		DUMP_WED(WED_MON_AMSDU_ENG_DMAD(8)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QFPL(8)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENI(8)),
++		DUMP_WED(WED_MON_AMSDU_ENG_QENO(8)),
++		DUMP_WED(WED_MON_AMSDU_ENG_MERG(8)),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8),
++			      WED_AMSDU_ENG_MAX_PL_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8),
++			      WED_AMSDU_ENG_MAX_QGPP_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++			      WED_AMSDU_ENG_CUR_ENTRY),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++			      WED_AMSDU_ENG_MAX_BUF_MERGED),
++		DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++			      WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++		DUMP_STR("WED QMEM INFO"),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_FQ_CNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_SP_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID0_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID1_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID2_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID3_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID4_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID5_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID6_QCNT),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID7_QCNT),
++
++		DUMP_STR("WED QMEM HEAD INFO"),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_FQ_HEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_SP_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID0_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID1_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID2_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID3_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID4_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID5_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID6_QHEAD),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID7_QHEAD),
++
++		DUMP_STR("WED QMEM TAIL INFO"),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_FQ_TAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_SP_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID0_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID1_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID2_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID3_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID4_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID5_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID6_QTAIL),
++		DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID7_QTAIL),
++
++		DUMP_STR("WED HIFTXD MSDU INFO"),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(1)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(2)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(3)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(4)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(5)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(6)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(7)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(8)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(9)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(10)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(11)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(12)),
++		DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(13)),
++	};
++
++	static const struct reg_dump *regs[] = {
++		&regs_common[0],
++		NULL,
++	};
++	struct mtk_wed_hw *hw = s->private;
++	struct mtk_wed_device *dev = hw->wed_dev;
++
++	if (!dev)
++		return 0;
++
++	dump_wed_regs(s, dev, regs);
++
++	return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_amsdu);
++
++static int
++wed_rtqm_show(struct seq_file *s, void *data)
++{
++	static const struct reg_dump regs_common[] = {
++		DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"),
++		DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT),
++		DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT),
++		DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT),
++
++
++		DUMP_STR("WED Route QM IGRS1(Legacy)"),
++		DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT),
++		DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT),
++		DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT),
++
++		DUMP_STR("WED Route QM IGRS2(RRO3.0)"),
++		DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
++		DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT),
++		DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT),
++
++		DUMP_STR("WED Route QM IGRS3(DEBUG)"),
++		DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
++		DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT),
++		DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)),
++		DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)),
++		DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT),
++
++		DUMP_END()
++	};
++
++	static const struct reg_dump *regs[] = {
++		&regs_common[0],
++		NULL,
++	};
++	struct mtk_wed_hw *hw = s->private;
++	struct mtk_wed_device *dev = hw->wed_dev;
++
++	if (!dev)
++		return 0;
++
++	dump_wed_regs(s, dev, regs);
++
++	return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_rtqm);
++
++
++static int
++wed_rro_show(struct seq_file *s, void *data)
++{
++	static const struct reg_dump regs_common[] = {
++		DUMP_STR("RRO/IND CMD CNT"),
++		DUMP_WED(WED_RX_IND_CMD_CNT(1)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(2)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(3)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(4)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(5)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(6)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(7)),
++		DUMP_WED(WED_RX_IND_CMD_CNT(8)),
++		DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9),
++			      WED_IND_CMD_MAGIC_CNT_FAIL_CNT),
++
++		DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)),
++		DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1),
++			      WED_ADDR_ELEM_SIG_FAIL_CNT),
++		DUMP_WED(WED_RX_MSDU_PG_CNT(1)),
++		DUMP_WED(WED_RX_MSDU_PG_CNT(2)),
++		DUMP_WED(WED_RX_MSDU_PG_CNT(3)),
++		DUMP_WED(WED_RX_MSDU_PG_CNT(4)),
++		DUMP_WED(WED_RX_MSDU_PG_CNT(5)),
++		DUMP_WED_MASK(WED_RX_PN_CHK_CNT,
++			      WED_PN_CHK_FAIL_CNT),
++
++		DUMP_END()
++	};
++
++	static const struct reg_dump *regs[] = {
++		&regs_common[0],
++		NULL,
++	};
++	struct mtk_wed_hw *hw = s->private;
++	struct mtk_wed_device *dev = hw->wed_dev;
++
++	if (!dev)
++		return 0;
++
++	dump_wed_regs(s, dev, regs);
++
++	return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_rro);
++
+ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+ {
+ 	struct dentry *dir;
+@@ -261,8 +745,20 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+ 	debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
+ 	debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
+ 	debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
+-	debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
+-	if (hw->version != 1) {
++	debugfs_create_u32("token_id", 0600, dir, &hw->token_id);
++	debugfs_create_file_unsafe("token_txd", 0600, dir, hw, &wed_token_txd_fops);
++
++	if (!mtk_wed_is_v1(hw)) {
++		debugfs_create_file_unsafe("rxinfo", 0400, dir, hw,
++					   &wed_rxinfo_fops);
+ 		wed_wo_mcu_debugfs(hw, dir);
++		if (mtk_wed_is_v3_or_greater(hw)) {
++			debugfs_create_file_unsafe("amsdu", 0400, dir, hw,
++						   &wed_amsdu_fops);
++			debugfs_create_file_unsafe("rtqm", 0400, dir, hw,
++						   &wed_rtqm_fops);
++			debugfs_create_file_unsafe("rro", 0400, dir, hw,
++						   &wed_rro_fops);
++		}
+ 	}
+ }
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+index be63406..18d1fb1 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+@@ -91,7 +91,7 @@ mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len)
+ {
+ 	struct mtk_wed_wo *wo = dev->hw->wed_wo;
+ 
+-	if (dev->hw->version == 1)
++	if (!mtk_wed_get_rx_capa(dev))
+ 		return 0;
+ 
+ 	if (WARN_ON(!wo))
+@@ -248,7 +248,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ 		u8 reserved1[15];
+ 	} __packed *region;
+ 
+-	char *mcu;
++	char *fw_name;
+ 	const struct mtk_wed_fw_trailer *hdr;
+ 	static u8 shared[MAX_REGION_SIZE] = {0};
+ 	const struct firmware *fw;
+@@ -256,13 +256,24 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ 	u32 ofs = 0;
+ 	u32 boot_cr, val;
+ 
+-	if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed"))
+-		mcu = MT7981_FIRMWARE_WO;
+-	else
+-		mcu = wo->hw->index ? MT7986_FIRMWARE_WO_2 :
+-				      MT7986_FIRMWARE_WO_1;
++	switch (wo->hw->version) {
++	case 2:
++		if (of_device_is_compatible(wo->hw->node,
++					    "mediatek,mt7981-wed"))
++			fw_name = MT7981_FIRMWARE_WO;
++		else
++			fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1
++						: MT7986_FIRMWARE_WO0;
++		break;
++	case 3:
++		fw_name = wo->hw->index ? MT7988_FIRMWARE_WO1
++					: MT7988_FIRMWARE_WO0;
++		break;
++	default:
++		return -EINVAL;
++	}
+ 
+-	ret = request_firmware(&fw, mcu, wo->hw->dev);
++	ret = request_firmware(&fw, fw_name, wo->hw->dev);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -307,8 +318,11 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ 	}
+ 
+ 	/* write the start address */
+-	boot_cr = wo->hw->index ?
+-		WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
++	if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)
++		boot_cr = WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR;
++	else
++		boot_cr = WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
++
+ 	wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
+ 
+ 	/* wo firmware reset */
+@@ -316,8 +330,10 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ 
+ 	val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
+ 
+-	val |= wo->hw->index ? WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK :
+-		WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
++	if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)
++		val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK;
++	else
++		val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
+ 
+ 	wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
+ 
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+index dbb17ae..6d4c9a7 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+@@ -17,8 +17,11 @@
+ #define WARP_ALREADY_DONE_STATUS (1)
+ 
+ #define MT7981_FIRMWARE_WO		"mediatek/mt7981_wo.bin"
+-#define MT7986_FIRMWARE_WO_1		"mediatek/mt7986_wo_0.bin"
+-#define MT7986_FIRMWARE_WO_2		"mediatek/mt7986_wo_1.bin"
++#define MT7986_FIRMWARE_WO0		"mediatek/mt7986_wo_0.bin"
++#define MT7986_FIRMWARE_WO1		"mediatek/mt7986_wo_1.bin"
++#define MT7988_FIRMWARE_WO0		"mediatek/mtk_wo_0.bin"
++#define MT7988_FIRMWARE_WO1		"mediatek/mtk_wo_1.bin"
++#define MT7988_FIRMWARE_WO2		"mediatek/mtk_wo_2.bin"
+ 
+ #define WOCPU_EMI_DEV_NODE		"mediatek,wocpu_emi"
+ #define WOCPU_ILM_DEV_NODE		"mediatek,wocpu_ilm"
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+index 645b8b1..0af264d 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+@@ -14,6 +14,9 @@
+ #define MTK_WDMA_DESC_CTRL_DMA_DONE		BIT(31)
+ #define MTK_WED_RX_BM_TOKEN			GENMASK(31, 16)
+ 
++#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE	BIT(29)
++#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE	BIT(31)
++
+ struct mtk_wdma_desc {
+ 	__le32 buf0;
+ 	__le32 ctrl;
+@@ -45,6 +48,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RESET_WDMA_INT_AGENT			BIT(19)
+ #define MTK_WED_RESET_RX_RRO_QM				BIT(20)
+ #define MTK_WED_RESET_RX_ROUTE_QM			BIT(21)
++#define MTK_WED_RESET_TX_AMSDU				BIT(22)
+ #define MTK_WED_RESET_WED				BIT(31)
+ 
+ #define MTK_WED_CTRL					0x00c
+@@ -52,6 +56,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY		BIT(1)
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_EN			BIT(2)
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY		BIT(3)
++#define MTK_WED_CTRL_WED_RX_IND_CMD_EN			BIT(5)
++#define MTK_WED_CTRL_WED_RX_PG_BM_EN			BIT(6)
++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU			BIT(7)
+ #define MTK_WED_CTRL_WED_TX_BM_EN			BIT(8)
+ #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
+ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
+@@ -62,9 +69,14 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_RX_RRO_QM_BUSY			BIT(15)
+ #define MTK_WED_CTRL_RX_ROUTE_QM_EN			BIT(16)
+ #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY			BIT(17)
++#define MTK_WED_CTRL_TX_TKID_ALI_EN			BIT(20)
++#define MTK_WED_CTRL_TX_TKID_ALI_BUSY			BIT(21)
++#define MTK_WED_CTRL_TX_AMSDU_EN			BIT(22)
++#define MTK_WED_CTRL_TX_AMSDU_BUSY			BIT(23)
+ #define MTK_WED_CTRL_FINAL_DIDX_READ			BIT(24)
+ #define MTK_WED_CTRL_ETH_DMAD_FMT			BIT(25)
+ #define MTK_WED_CTRL_MIB_READ_CLEAR			BIT(28)
++#define MTK_WED_CTRL_FLD_MIB_RD_CLR			BIT(28)
+ 
+ #define MTK_WED_EXT_INT_STATUS				0x020
+ #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR		BIT(0)
+@@ -72,12 +84,10 @@ struct mtk_wdma_desc {
+ #define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID	BIT(4)
+ #define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH		BIT(8)
+ #define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH		BIT(9)
+-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+-#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH		BIT(10)
+-#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH		BIT(11)
+-#endif
+-#define MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY		BIT(12)
+-#define MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER		BIT(13)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2		BIT(10)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2		BIT(11)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH		BIT(12)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH		BIT(13)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR	BIT(16)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR	BIT(17)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT		BIT(18)
+@@ -94,17 +104,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_EXT_INT_STATUS_ERROR_MASK		(MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
+ 							 MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
+ 							 MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
+-							 MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY | \
+-							 MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER | \
+ 							 MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
+ 							 MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
+ 							 MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
+-							 MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR | \
+-							 MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
++							 MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR)
+ 
+ #define MTK_WED_EXT_INT_MASK				0x028
+ #define MTK_WED_EXT_INT_MASK1				0x02c
+ #define MTK_WED_EXT_INT_MASK2				0x030
++#define MTK_WED_EXT_INT_MASK3				0x034
+ 
+ #define MTK_WED_STATUS					0x060
+ #define MTK_WED_STATUS_TX				GENMASK(15, 8)
+@@ -112,12 +120,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_BM_CTRL				0x080
+ #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM			GENMASK(6, 0)
+ #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM			GENMASK(22, 16)
++#define MTK_WED_TX_BM_CTRL_LEGACY_EN			BIT(26)
++#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT		BIT(27)
+ #define MTK_WED_TX_BM_CTRL_PAUSE			BIT(28)
+ 
+ #define MTK_WED_TX_BM_BASE				0x084
++#define MTK_WED_TX_BM_INIT_PTR				0x088
++#define MTK_WED_TX_BM_SW_TAIL_IDX			GENMASK(16, 0)
++#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX			BIT(16)
+ 
+-#define MTK_WED_TX_BM_TKID				0x088
+-#define MTK_WED_TX_BM_TKID_V2				0x0c8
+ #define MTK_WED_TX_BM_TKID_START			GENMASK(15, 0)
+ #define MTK_WED_TX_BM_TKID_END				GENMASK(31, 16)
+ 
+@@ -140,6 +151,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM		GENMASK(22, 16)
+ #define MTK_WED_TX_TKID_CTRL_PAUSE			BIT(28)
+ 
++#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3		GENMASK(7, 0)
++#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3		GENMASK(23, 16)
++
+ #define MTK_WED_TX_TKID_DYN_THR				0x0e0
+ #define MTK_WED_TX_TKID_DYN_THR_LO			GENMASK(6, 0)
+ #define MTK_WED_TX_TKID_DYN_THR_HI			GENMASK(22, 16)
+@@ -205,12 +219,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC	BIT(5)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC	BIT(6)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC	BIT(7)
+-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER	GENMASK(18, 16)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER	GENMASK(15, 12)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4	BIT(18)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT	BIT(19)
+-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK	BIT(20)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR		BIT(21)
+ #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP		BIT(24)
++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST		BIT(25)
+ #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV		BIT(28)
++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK		BIT(30)
+ 
+ /* CONFIG_MEDIATEK_NETSYS_V1 */
+ #define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE		GENMASK(5, 4)
+@@ -273,9 +290,11 @@ struct mtk_wdma_desc {
+ #define MTK_WED_PCIE_INT_TRIGGER_STATUS			BIT(16)
+ 
+ #define MTK_WED_PCIE_INT_CTRL				0x57c
+-#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA		BIT(20)
++#define MTK_WED_PCIE_INT_CTRL_POLL_EN			GENMASK(13, 12)
+ #define MTK_WED_PCIE_INT_CTRL_SRC_SEL			GENMASK(17, 16)
+-#define MTK_WED_PCIE_INT_CTRL_POLL_EN 			GENMASK(13, 12)
++#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA		BIT(20)
++#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER		BIT(21)
++
+ #define MTK_WED_WPDMA_CFG_BASE				0x580
+ #define MTK_WED_WPDMA_CFG_INT_MASK			0x584
+ #define MTK_WED_WPDMA_CFG_TX				0x588
+@@ -304,20 +323,50 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX			GENMASK(25, 24)
+ 
+ #define MTK_WED_WPDMA_RX_GLO_CFG			0x76c
+-#define MTK_WED_WPDMA_RX_RING				0x770
++#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++#define MTK_WED_WPDMA_RX_RING0				0x770
++#else
++#define MTK_WED_WPDMA_RX_RING0				0x7d0
++#endif
++#define MTK_WED_WPDMA_RX_RING1				0x7d8
+ 
+ #define MTK_WED_WPDMA_RX_D_MIB(_n)			(0x774 + (_n) * 4)
+ #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n)		(0x784 + (_n) * 4)
+ #define MTK_WED_WPDMA_RX_D_COHERENT_MIB			0x78c
+ 
++#define MTK_WED_WPDMA_RX_D_PREF_CFG			0x7b4
++#define MTK_WED_WPDMA_RX_D_PREF_EN			BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE		GENMASK(12, 8)
++#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES		GENMASK(21, 16)
++
++#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX		0x7b8
++#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR		BIT(15)
++
++#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX		0x7bc
++
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG		0x7c0
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR		BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR		BIT(16)
++
+ #define MTK_WED_WDMA_RING_TX				0x800
+ 
+ #define MTK_WED_WDMA_TX_MIB				0x810
+ 
+-
+ #define MTK_WED_WDMA_RING_RX(_n)			(0x900 + (_n) * 0x10)
+ #define MTK_WED_WDMA_RX_THRES(_n)			(0x940 + (_n) * 0x4)
+ 
++#define MTK_WED_WDMA_RX_PREF_CFG			0x950
++#define MTK_WED_WDMA_RX_PREF_EN				BIT(0)
++#define MTK_WED_WDMA_RX_PREF_BURST_SIZE			GENMASK(12, 8)
++#define MTK_WED_WDMA_RX_PREF_LOW_THRES			GENMASK(21, 16)
++#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR		BIT(24)
++#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR		BIT(25)
++#define MTK_WED_WDMA_RX_PREF_DDONE2_EN			BIT(26)
++
++#define MTK_WED_WDMA_RX_PREF_FIFO_CFG			0x95C
++#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR		BIT(0)
++#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR		BIT(16)
++
+ #define MTK_WED_WDMA_GLO_CFG				0xa04
+ #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN			BIT(0)
+ #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK		BIT(1)
+@@ -350,6 +399,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE		GENMASK(17, 16)
+ 
+ #define MTK_WED_WDMA_INT_CTRL				0xa2c
++#define MTK_WED_WDMA_INT_POLL_PRD			GENMASK(7, 0)
+ #define MTK_WED_WDMA_INT_POLL_SRC_SEL			GENMASK(17, 16)
+ 
+ #define MTK_WED_WDMA_CFG_BASE				0xaa0
+@@ -369,7 +419,7 @@ struct mtk_wdma_desc {
+ 
+ #define MTK_WED_RX_BM_BASE				0xd84
+ #define MTK_WED_RX_BM_INIT_PTR				0xd88
+-#define MTK_WED_RX_BM_SW_TAIL 				GENMASK(15, 0)
++#define MTK_WED_RX_BM_SW_TAIL				GENMASK(15, 0)
+ #define MTK_WED_RX_BM_INIT_SW_TAIL			BIT(16)
+ 
+ #define MTK_WED_RX_PTR					0xd8c
+@@ -411,6 +461,18 @@ struct mtk_wdma_desc {
+ #define MTK_WDMA_INT_GRP1				0x250
+ #define MTK_WDMA_INT_GRP2				0x254
+ 
++#define MTK_WDMA_PREF_TX_CFG				0x2d0
++#define MTK_WDMA_PREF_TX_CFG_PREF_EN			BIT(0)
++
++#define MTK_WDMA_PREF_RX_CFG				0x2dc
++#define MTK_WDMA_PREF_RX_CFG_PREF_EN			BIT(0)
++
++#define MTK_WDMA_WRBK_TX_CFG				0x300
++#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN			BIT(30)
++
++#define MTK_WDMA_WRBK_RX_CFG				0x344
++#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN			BIT(30)
++
+ #define MTK_PCIE_MIRROR_MAP(n)				((n) ? 0x4 : 0x0)
+ #define MTK_PCIE_MIRROR_MAP_EN				BIT(0)
+ #define MTK_PCIE_MIRROR_MAP_WED_ID			BIT(1)
+@@ -419,11 +481,36 @@ struct mtk_wdma_desc {
+ #define HIFSYS_DMA_AG_MAP				0x008
+ 
+ #define MTK_WED_RTQM_GLO_CFG				0xb00
+-#define MTK_WED_RTQM_BUSY	 			BIT(1)
+-#define MTK_WED_RTQM_Q_RST	 			BIT(2)
++#define MTK_WED_RTQM_BUSY				BIT(1)
++#define MTK_WED_RTQM_Q_RST				BIT(2)
+ #define MTK_WED_RTQM_Q_DBG_BYPASS			BIT(5)
+ #define MTK_WED_RTQM_TXDMAD_FPORT			GENMASK(23, 20)
+ 
++#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT		0xb1c
++#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n)		(0xb20 + (_n) * 0x4)
++#define	MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT			0xb28
++#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n)		(0xb2c + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS0_FDROP_CNT			0xb34
++
++
++#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT		0xb44
++#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n)		(0xb48 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT			0xb50
++#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n)		(0xb54 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS1_FDROP_CNT			0xb5c
++
++#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT		0xb6c
++#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n)		(0xb70 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT			0xb78
++#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n)		(0xb7c + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS2_FDROP_CNT			0xb84
++
++#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT		0xb94
++#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n)		(0xb98 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT			0xba0
++#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n)		(0xba4 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS3_FDROP_CNT			0xbac
++
+ #define MTK_WED_RTQM_R2H_MIB(_n)			(0xb70 + (_n) * 0x4)
+ #define MTK_WED_RTQM_R2Q_MIB(_n)			(0xb78 + (_n) * 0x4)
+ #define MTK_WED_RTQM_Q2N_MIB				0xb80
+@@ -432,21 +519,39 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RTQM_Q2B_MIB				0xb8c
+ #define MTK_WED_RTQM_PFDBK_MIB				0xb90
+ 
++#define MTK_WED_RTQM_ENQ_CFG0				0xbb8
++#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT		GENMASK(15, 12)
++
++#define MTK_WED_RTQM_FDROP_MIB				0xb84
++#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT			0xbbc
++#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT			0xbc0
++#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT			0xbc4
++#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT			0xbc8
++#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT			0xbcc
++#define MTK_WED_RTQM_ENQ_ERR_CNT			0xbd0
++
++#define MTK_WED_RTQM_DEQ_DMAD_CNT			0xbd8
++#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT			0xbdc
++#define MTK_WED_RTQM_DEQ_PKT_CNT			0xbe0
++#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT			0xbe4
++#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT			0xbe8
++#define MTK_WED_RTQM_DEQ_ERR_CNT			0xbec
++
+ #define MTK_WED_RROQM_GLO_CFG				0xc04
+ #define MTK_WED_RROQM_RST_IDX				0xc08
+-#define MTK_WED_RROQM_RST_IDX_MIOD 			BIT(0)
+-#define MTK_WED_RROQM_RST_IDX_FDBK 			BIT(4)
++#define MTK_WED_RROQM_RST_IDX_MIOD			BIT(0)
++#define MTK_WED_RROQM_RST_IDX_FDBK			BIT(4)
+ 
+ #define MTK_WED_RROQM_MIOD_CTRL0			0xc40
+ #define MTK_WED_RROQM_MIOD_CTRL1			0xc44
+-#define MTK_WED_RROQM_MIOD_CNT 				GENMASK(11, 0)
++#define MTK_WED_RROQM_MIOD_CNT				GENMASK(11, 0)
+ 
+ #define MTK_WED_RROQM_MIOD_CTRL2			0xc48
+ #define MTK_WED_RROQM_MIOD_CTRL3			0xc4c
+ 
+ #define MTK_WED_RROQM_FDBK_CTRL0			0xc50
+ #define MTK_WED_RROQM_FDBK_CTRL1			0xc54
+-#define MTK_WED_RROQM_FDBK_CNT 				GENMASK(11, 0)
++#define MTK_WED_RROQM_FDBK_CNT				GENMASK(11, 0)
+ 
+ #define MTK_WED_RROQM_FDBK_CTRL2			0xc58
+ 
+@@ -454,7 +559,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RROQ_BASE_H				0xc84
+ 
+ #define MTK_WED_RROQM_MIOD_CFG                          0xc8c
+-#define MTK_WED_RROQM_MIOD_MID_DW 			GENMASK(5, 0)
++#define MTK_WED_RROQM_MIOD_MID_DW			GENMASK(5, 0)
+ #define MTK_WED_RROQM_MIOD_MOD_DW			GENMASK(13, 8)
+ #define MTK_WED_RROQM_MIOD_ENTRY_DW			GENMASK(22, 16)
+ 
+@@ -468,20 +573,206 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RROQM_FDBK_ANC_MIB			0xce8
+ #define MTK_WED_RROQM_FDBK_ANC2H_MIB			0xcec
+ 
+-#define MTK_WED_RX_BM_RX_DMAD  				0xd80
++#define MTK_WED_RX_BM_RX_DMAD				0xd80
+ #define MTK_WED_RX_BM_BASE				0xd84
+ #define MTK_WED_RX_BM_INIT_PTR				0xd88
+-#define MTK_WED_RX_BM_PTR	      			0xd8c
+-#define MTK_WED_RX_BM_PTR_HEAD				GENMASK(32, 16)
++#define MTK_WED_RX_BM_PTR				0xd8c
+ #define MTK_WED_RX_BM_PTR_TAIL				GENMASK(15, 0)
++#define MTK_WED_RX_BM_PTR_HEAD				GENMASK(32, 16)
+ 
+-#define MTK_WED_RX_BM_BLEN	      			0xd90
++#define MTK_WED_RX_BM_BLEN				0xd90
+ #define MTK_WED_RX_BM_STS				0xd94
+ #define MTK_WED_RX_BM_INTF2				0xd98
+ #define MTK_WED_RX_BM_INTF				0xd9c
+ #define MTK_WED_RX_BM_ERR_STS				0xda8
+ 
+-#define MTK_WED_WOCPU_VIEW_MIOD_BASE		 	0x8000
++#define MTK_RRO_IND_CMD_SIGNATURE			0xe00
++#define MTK_RRO_IND_CMD_DMA_IDX				GENMASK(11, 0)
++#define MTK_RRO_IND_CMD_MAGIC_CNT			GENMASK(30, 28)
++
++#define MTK_WED_IND_CMD_RX_CTRL0			0xe04
++#define MTK_WED_IND_CMD_PROC_IDX			GENMASK(11, 0)
++#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT		GENMASK(19, 16)
++#define MTK_WED_IND_CMD_MAGIC_CNT			GENMASK(30, 28)
++
++#define MTK_WED_IND_CMD_RX_CTRL1			0xe08
++#define MTK_WED_IND_CMD_RX_CTRL2			0xe0c
++#define MTK_WED_IND_CMD_MAX_CNT				GENMASK(11, 0)
++#define MTK_WED_IND_CMD_BASE_M				GENMASK(19, 16)
++
++#define MTK_WED_RRO_CFG0				0xe10
++#define MTK_WED_RRO_CFG1				0xe14
++#define MTK_WED_RRO_CFG1_MAX_WIN_SZ			GENMASK(31, 29)
++#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M			GENMASK(19, 16)
++#define MTK_WED_RRO_CFG1_PARTICL_SE_ID			GENMASK(11, 0)
++
++#define MTK_WED_ADDR_ELEM_CFG0				0xe18
++#define MTK_WED_ADDR_ELEM_CFG1				0xe1c
++#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT		GENMASK(19, 16)
++
++#define MTK_WED_ADDR_ELEM_TBL_CFG			0xe20
++#define MTK_WED_ADDR_ELEM_TBL_OFFSET			GENMASK(6, 0)
++#define MTK_WED_ADDR_ELEM_TBL_RD_RDY			BIT(28)
++#define MTK_WED_ADDR_ELEM_TBL_WR_RDY			BIT(29)
++#define MTK_WED_ADDR_ELEM_TBL_RD			BIT(30)
++#define MTK_WED_ADDR_ELEM_TBL_WR			BIT(31)
++
++#define MTK_WED_RADDR_ELEM_TBL_WDATA			0xe24
++#define MTK_WED_RADDR_ELEM_TBL_RDATA			0xe28
++
++#define MTK_WED_PN_CHECK_CFG				0xe30
++#define MTK_WED_PN_CHECK_SE_ID				GENMASK(11, 0)
++#define MTK_WED_PN_CHECK_RD_RDY				BIT(28)
++#define MTK_WED_PN_CHECK_WR_RDY				BIT(29)
++#define MTK_WED_PN_CHECK_RD				BIT(30)
++#define MTK_WED_PN_CHECK_WR				BIT(31)
++
++#define MTK_WED_PN_CHECK_WDATA_M			0xe38
++#define MTK_WED_PN_CHECK_IS_FIRST			BIT(17)
++
++#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n)		(0xe44 + (_n) * 0x8)
++
++#define MTK_WED_RRO_MSDU_PG_RING2_CFG			0xe58
++#define MTK_WED_RRO_MSDU_PG_DRV_CLR			BIT(26)
++#define MTK_WED_RRO_MSDU_PG_DRV_EN			BIT(31)
++
++#define MTK_WED_RRO_MSDU_PG_CTRL0(_n)			(0xe5c + (_n) * 0xc)
++#define MTK_WED_RRO_MSDU_PG_CTRL1(_n)			(0xe60 + (_n) * 0xc)
++#define MTK_WED_RRO_MSDU_PG_CTRL2(_n)			(0xe64 + (_n) * 0xc)
++
++#define MTK_WED_RRO_RX_D_RX(_n)				(0xe80 + (_n) * 0x10)
++
++#define MTK_WED_RRO_RX_MAGIC_CNT			BIT(13)
++
++#define MTK_WED_RRO_RX_D_CFG(_n)			(0xea0 + (_n) * 0x4)
++#define MTK_WED_RRO_RX_D_DRV_CLR			BIT(26)
++#define MTK_WED_RRO_RX_D_DRV_EN				BIT(31)
++
++#define MTK_WED_RRO_PG_BM_RX_DMAM			0xeb0
++#define MTK_WED_RRO_PG_BM_RX_SDL0			GENMASK(13, 0)
++
++#define MTK_WED_RRO_PG_BM_BASE				0xeb4
++#define MTK_WED_RRO_PG_BM_INIT_PTR			0xeb8
++#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX			GENMASK(15, 0)
++#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX		BIT(16)
++
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX			0xeec
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN		BIT(0)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR		BIT(1)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG	GENMASK(6, 2)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN		BIT(8)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR		BIT(9)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG	GENMASK(14, 10)
++
++#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG		0xef4
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN		BIT(0)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR		BIT(1)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG	GENMASK(6, 2)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN		BIT(8)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR		BIT(9)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG	GENMASK(14, 10)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN		BIT(16)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR		BIT(17)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG	GENMASK(22, 18)
++
++#define MTK_WED_RX_IND_CMD_CNT0				0xf20
++#define MTK_WED_RX_IND_CMD_DBG_CNT_EN			BIT(31)
++
++#define MTK_WED_RX_IND_CMD_CNT(_n)			(0xf20 + (_n) * 0x4)
++#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT		GENMASK(15, 0)
++
++#define MTK_WED_RX_ADDR_ELEM_CNT(_n)			(0xf48 + (_n) * 0x4)
++#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT			GENMASK(15, 0)
++#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT		GENMASK(31, 16)
++#define MTK_WED_ADDR_ELEM_ACKSN_CNT			GENMASK(27, 0)
++
++#define MTK_WED_RX_MSDU_PG_CNT(_n)			(0xf5c + (_n) * 0x4)
++
++#define MTK_WED_RX_PN_CHK_CNT				0xf70
++#define MTK_WED_PN_CHK_FAIL_CNT				GENMASK(15, 0)
++
++#define MTK_WED_WOCPU_VIEW_MIOD_BASE			0x8000
+ #define MTK_WED_PCIE_INT_MASK				0x0
+ 
++#define MTK_WED_AMSDU_FIFO				0x1800
++#define MTK_WED_AMSDU_IS_PRIOR0_RING			BIT(10)
++
++#define MTK_WED_AMSDU_STA_INFO				0x01810
++#define MTK_WED_AMSDU_STA_INFO_DO_INIT			BIT(0)
++#define MTK_WED_AMSDU_STA_INFO_SET_INIT			BIT(1)
++
++#define MTK_WED_AMSDU_STA_INFO_INIT			0x01814
++#define MTK_WED_AMSDU_STA_WTBL_HDRT_MODE		BIT(0)
++#define MTK_WED_AMSDU_STA_RMVL				BIT(1)
++#define MTK_WED_AMSDU_STA_MAX_AMSDU_LEN			GENMASK(7, 2)
++#define MTK_WED_AMSDU_STA_MAX_AMSDU_NUM			GENMASK(11, 8)
++
++#define MTK_WED_AMSDU_HIFTXD_BASE_L(_n)			(0x1980 + (_n) * 0x4)
++
++#define MTK_WED_AMSDU_PSE				0x1910
++#define MTK_WED_AMSDU_PSE_RESET				BIT(16)
++
++#define MTK_WED_AMSDU_HIFTXD_CFG			0x1968
++#define MTK_WED_AMSDU_HIFTXD_SRC			GENMASK(16, 15)
++
++#define MTK_WED_MON_AMSDU_FIFO_DMAD			0x1a34
++
++#define MTK_WED_MON_AMSDU_ENG_DMAD(_n)			(0x1a80 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QFPL(_n)			(0x1a84 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QENI(_n)			(0x1a88 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QENO(_n)			(0x1a8c + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_MERG(_n)			(0x1a90 + (_n) * 0x50)
++
++#define MTK_WED_MON_AMSDU_ENG_CNT8(_n)			(0x1a94 + (_n) * 0x50)
++#define MTK_WED_AMSDU_ENG_MAX_QGPP_CNT			GENMASK(10, 0)
++#define MTK_WED_AMSDU_ENG_MAX_PL_CNT			GENMASK(27, 16)
++
++#define MTK_WED_MON_AMSDU_ENG_CNT9(_n)			(0x1a98 + (_n) * 0x50)
++#define MTK_WED_AMSDU_ENG_CUR_ENTRY			GENMASK(10, 0)
++#define MTK_WED_AMSDU_ENG_MAX_BUF_MERGED		GENMASK(20, 16)
++#define MTK_WED_AMSDU_ENG_MAX_MSDU_MERGED		GENMASK(28, 24)
++
++#define MTK_WED_MON_AMSDU_QMEM_STS1			0x1e04
++
++#define MTK_WED_MON_AMSDU_QMEM_CNT(_n)			(0x1e0c + (_n) * 0x4)
++#define MTK_WED_AMSDU_QMEM_FQ_CNT			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QCNT			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QCNT			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QCNT			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QCNT			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QCNT			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QCNT			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QCNT			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QCNT			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QCNT			GENMASK(11, 0)
++
++#define MTK_WED_MON_AMSDU_QMEM_PTR(_n)			(0x1e20 + (_n) * 0x4)
++#define MTK_WED_AMSDU_QMEM_FQ_HEAD			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QHEAD			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QHEAD			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QHEAD			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QHEAD			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QHEAD			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QHEAD			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QHEAD			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QHEAD			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QHEAD			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_FQ_TAIL			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QTAIL			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QTAIL			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QTAIL			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QTAIL			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QTAIL			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QTAIL			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QTAIL			GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QTAIL			GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QTAIL			GENMASK(11, 0)
++
++#define MTK_WED_MON_AMSDU_HIFTXD_FETCH_MSDU(_n)		(0x1ec4 + (_n) * 0x4)
++
++#define MTK_WED_PCIE_BASE			0x11280000
++
++#define MTK_WED_PCIE_BASE0			0x11300000
++#define MTK_WED_PCIE_BASE1			0x11310000
++#define MTK_WED_PCIE_BASE2			0x11290000
+ #endif
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index b2abebe..a9e455d 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -880,6 +880,13 @@ struct net_device_path {
+ 			u8 queue;
+ 			u16 wcid;
+ 			u8 bss;
++			u32 usr_info;
++			u8 tid;
++			u8 is_fixedrate;
++			u8 is_prior;
++			u8 is_sp;
++			u8 hf;
++			u8 amsdu;
+ 		} mtk_wdma;
+ 	};
+ };
+diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
+index 470beb2..e81e41f 100644
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -5,9 +5,12 @@
+ #include <linux/rcupdate.h>
+ #include <linux/regmap.h>
+ #include <linux/pci.h>
++#include <linux/skbuff.h>
++#include <linux/iopoll.h>
+ 
+ #define MTK_WED_TX_QUEUES		2
+ #define MTK_WED_RX_QUEUES		2
++#define MTK_WED_RX_PAGE_QUEUES		3
+ 
+ #define WED_WO_STA_REC			0x6
+ 
+@@ -43,7 +46,7 @@ enum mtk_wed_wo_cmd {
+ 	MTK_WED_WO_CMD_WED_END
+ };
+ 
+-struct mtk_rxbm_desc {
++struct mtk_wed_bm_desc {
+ 	__le32 buf0;
+ 	__le32 token;
+ } __packed __aligned(4);
+@@ -74,6 +77,11 @@ struct mtk_wed_wo_rx_stats {
+ 	__le32 rx_drop_cnt;
+ };
+ 
++struct mtk_wed_buf {
++	void *p;
++	dma_addr_t phy_addr;
++};
++
+ struct mtk_wed_device {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ 	const struct mtk_wed_ops *ops;
+@@ -92,10 +100,13 @@ struct mtk_wed_device {
+ 	struct mtk_wed_ring txfree_ring;
+ 	struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES];
+ 	struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
++	struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES];
++	struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES];
++	struct mtk_wed_ring ind_cmd_ring;
+ 
+ 	struct {
+ 		int size;
+-		void **pages;
++		struct mtk_wed_buf *pages;
+ 		struct mtk_wdma_desc *desc;
+ 		dma_addr_t desc_phys;
+ 	} tx_buf_ring;
+@@ -103,7 +114,7 @@ struct mtk_wed_device {
+  	struct {
+  		int size;
+  		struct page_frag_cache rx_page;
+-		struct mtk_rxbm_desc *desc;
++		struct mtk_wed_bm_desc *desc;
+  		dma_addr_t desc_phys;
+  	} rx_buf_ring;
+ 
+@@ -114,6 +125,13 @@ struct mtk_wed_device {
+ 		dma_addr_t fdbk_phys;
+ 	} rro;
+ 
++	struct {
++		int size;
++		struct mtk_wed_buf *pages;
++		struct mtk_wed_bm_desc *desc;
++		dma_addr_t desc_phys;
++	} hw_rro;
++
+ 	/* filled by driver: */
+ 	struct {
+ 		union {
+@@ -123,6 +141,7 @@ struct mtk_wed_device {
+ 		enum mtk_wed_bus_tye bus_type;
+ 		void __iomem *base;
+ 		u32 phy_base;
++		u32 id;
+ 
+ 		u32 wpdma_phys;
+ 		u32 wpdma_int;
+@@ -130,10 +149,14 @@ struct mtk_wed_device {
+ 		u32 wpdma_tx;
+ 		u32 wpdma_txfree;
+ 		u32 wpdma_rx_glo;
+-		u32 wpdma_rx;
++		u32 wpdma_rx[MTK_WED_RX_QUEUES];
++		u32 wpdma_rx_rro[MTK_WED_RX_QUEUES];
++		u32 wpdma_rx_pg;
+ 
+ 		u8 tx_tbit[MTK_WED_TX_QUEUES];
+ 		u8 rx_tbit[MTK_WED_RX_QUEUES];
++		u8 rro_rx_tbit[MTK_WED_RX_QUEUES];
++		u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES];
+ 		u8 txfree_tbit;
+ 
+ 		u16 token_start;
+@@ -141,8 +164,22 @@ struct mtk_wed_device {
+ 		unsigned int rx_nbuf;
+ 		unsigned int rx_npkt;
+ 		unsigned int rx_size;
++		unsigned int amsdu_max_len;
+ 
+ 		bool wcid_512;
++		bool hw_rro;
++		bool msi;
++
++		u8 amsdu_max_subframes;
++
++		struct {
++			u8 se_group_nums;
++			u16 win_size;
++			u16 particular_sid;
++			u32 ack_sn_addr;
++			dma_addr_t particular_se_phys;
++			dma_addr_t addr_elem_phys[1024];
++		} ind_cmd;
+ 
+ 		u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
+ 		int (*offload_enable)(struct mtk_wed_device *wed);
+@@ -185,6 +222,13 @@ struct mtk_wed_ops {
+ 
+ 	u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
++	void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask);
++	void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++				  void __iomem *regs);
++	void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++				      void __iomem *regs);
++	int (*ind_rx_ring_setup)(struct mtk_wed_device *dev,
++				 void __iomem *regs);
+ };
+ 
+ extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
+@@ -213,12 +257,25 @@ static inline bool
+ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
++	if (dev->version == 3)
++		return dev->wlan.hw_rro;
++
+ 	return dev->version != 1;
+ #else
+ 	return false;
+ #endif
+ }
+ 
++static inline bool
++mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++	return dev->version == 3;
++#else
++	return false;
++#endif
++}
++
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ #define mtk_wed_device_active(_dev) !!(_dev)->ops
+ #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
+@@ -245,6 +302,14 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
+ 	(_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
++#define mtk_wed_device_start_hw_rro(_dev, _mask) \
++	(_dev)->ops->start_hw_rro(_dev, _mask)
++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
++	(_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
++	(_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \
++	(_dev)->ops->ind_rx_ring_setup(_dev, _regs)
+ #else
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -264,6 +329,10 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_stop(_dev) do {} while (0)
+ #define mtk_wed_device_dma_reset(_dev) do {} while (0)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
++#define mtk_wed_device_start_hw_rro(_dev, _mask) do {} while (0)
++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs)  -ENODEV
++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs)  -ENODEV
+ #endif
+ 
+ #endif
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch
new file mode 100644
index 0000000..9778202
--- /dev/null
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3020-mtk-wed-add-wed3-ser-support.patch
@@ -0,0 +1,705 @@
+From 11f1e7684e9cadd83038694396ebd99792cff590 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Mon, 18 Sep 2023 13:22:44 +0800
+Subject: [PATCH 20/24] mtk wed add wed3 ser support
+
+---
+ drivers/net/ethernet/mediatek/mtk_wed.c      | 340 ++++++++++++++++---
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h |  68 +++-
+ include/linux/soc/mediatek/mtk_wed.h         |   8 +-
+ 3 files changed, 368 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index 2fed493..7f14d43 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -110,24 +110,88 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
+ 	return wdma_r32(dev, MTK_WDMA_GLO_CFG);
+ }
+ 
+-static u32
+-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++static void
++mtk_wdma_v3_rx_reset(struct mtk_wed_device *dev)
+ {
+-	if (wed_r32(dev, reg) & mask)
+-		return true;
+-
+-	return false;
+-}
++	u32 status;
+ 
+-static int
+-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+-	int sleep = 1000;
+-	int timeout = 100 * sleep;
+-	u32 val;
++	if (!mtk_wed_is_v3_or_greater(dev->hw))
++		return;
+ 
+-	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
+-				 timeout, false, dev, reg, mask);
++	wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++	wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG))
++		dev_err(dev->hw->dev, "rx reset failed\n");
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG))
++		dev_err(dev->hw->dev, "rx reset failed\n");
++
++	wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++	wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG))
++		dev_err(dev->hw->dev, "rx reset failed\n");
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG))
++		dev_err(dev->hw->dev, "rx reset failed\n");
++
++	/* prefetch FIFO */
++	wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
++		 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
++		 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
++	wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
++		 MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
++		 MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
++
++	/* core FIFO */
++	wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG,
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
++	wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG,
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
++
++	/* writeback FIFO */
++	wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0),
++		 MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++	wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1),
++		 MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++
++	wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0),
++		 MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1),
++		 MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++
++	/* prefetch ring status */
++	wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG,
++		 MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG,
++		 MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
++
++	/* writeback ring status */
++	wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG,
++		 MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG,
++		 MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
+ }
+ 
+ static int
+@@ -142,6 +206,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ 	if (ret)
+ 		dev_err(dev->hw->dev, "rx reset failed \n");
+ 
++	mtk_wdma_v3_rx_reset(dev);
+ 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
+ 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+ 
+@@ -156,6 +221,101 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ 	return ret;
+ }
+ 
++static u32
++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++	return !!(wed_r32(dev, reg) & mask);
++}
++
++static int
++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++	int sleep = 15000;
++	int timeout = 100 * sleep;
++	u32 val;
++
++	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
++				 timeout, false, dev, reg, mask);
++}
++
++static void
++mtk_wdma_v3_tx_reset(struct mtk_wed_device *dev)
++{
++	u32 status;
++
++	if (!mtk_wed_is_v3_or_greater(dev->hw))
++		return;
++
++	wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++	wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG))
++		dev_err(dev->hw->dev, "tx reset failed\n");
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG))
++		dev_err(dev->hw->dev, "tx reset failed\n");
++
++	wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++	wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG))
++		dev_err(dev->hw->dev, "tx reset failed\n");
++
++	if (read_poll_timeout(wdma_r32, status,
++			      !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY),
++			      0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG))
++		dev_err(dev->hw->dev, "tx reset failed\n");
++
++	/* prefetch FIFO */
++	wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
++		 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
++		 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
++	wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
++		 MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
++		 MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
++
++	/* core FIFO */
++	wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG,
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
++	wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG,
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
++		 MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
++
++	/* writeback FIFO */
++	wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0),
++		 MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++	wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1),
++		 MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++
++	wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0),
++		 MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1),
++		 MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++
++	/* prefetch ring status */
++	wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG,
++		 MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG,
++		 MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
++
++	/* writeback ring status */
++	wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG,
++		 MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
++	wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG,
++		 MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
++}
++
+ static void
+ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+ {
+@@ -167,6 +327,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+ 			       !(status & mask), 0, 10000))
+ 		dev_err(dev->hw->dev, "tx reset failed \n");
+ 
++	mtk_wdma_v3_tx_reset(dev);
+ 	wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+ 	wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+ 
+@@ -1402,25 +1563,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
+ 	}
+ }
+ 
+-static u32
+-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+-	if (wed_r32(dev, reg) & mask)
+-		return true;
+-
+-	return false;
+-}
+-
+-static int
+-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+-	int sleep = 1000;
+-	int timeout = 100 * sleep;
+-	u32 val;
+-
+-	return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
+-				 timeout, false, dev, reg, mask);
+-}
+ 
+ static int
+ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1436,13 +1578,32 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	if (dev->wlan.hw_rro) {
++		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
++		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS,
++				  MTK_WED_RX_IND_CMD_BUSY);
++		mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG);
++	}
++
+ 	wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
+ 	ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
+ 				MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
++	if (!ret && mtk_wed_is_v3_or_greater(dev->hw))
++		ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++					 MTK_WED_WPDMA_RX_D_PREF_BUSY);
+ 	if (ret) {
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
+ 	} else {
++		if (mtk_wed_is_v3_or_greater(dev->hw)) {
++			/*1.a. Disable Prefetch HW*/
++			wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, MTK_WED_WPDMA_RX_D_PREF_EN);
++			mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++					  MTK_WED_WPDMA_RX_D_PREF_BUSY);
++			wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
++				MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL);
++		}
++
+ 		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+ 			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
+ 			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
+@@ -1470,15 +1631,36 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 		wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
+ 	}
+ 
++	if (dev->wlan.hw_rro) {
++		/* Disable RRO MSDU Page Drv */
++		wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
++
++		/* Disable RRO Data Drv */
++		wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
++
++		/* RRO MSDU Page Drv Reset */
++		wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
++		mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++				  MTK_WED_RRO_MSDU_PG_DRV_CLR);
++
++		/* RRO Data Drv Reset */
++		wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_CLR);
++		mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2),
++				  MTK_WED_RRO_RX_D_DRV_CLR);
++	}
++
+ 	/* reset route qm */
+ 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
+ 	ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+ 				MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
+ 	if (ret) {
+ 		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
++	} else if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		wed_set(dev, MTK_WED_RTQM_RST, BIT(0));
++		wed_clr(dev, MTK_WED_RTQM_RST, BIT(0));
++		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
+ 	} else {
+-		wed_set(dev, MTK_WED_RTQM_GLO_CFG,
+-			MTK_WED_RTQM_Q_RST);
++		wed_set(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
+ 	}
+ 
+ 	/* reset tx wdma */
+@@ -1486,8 +1668,12 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 
+ 	/* reset tx wdma drv */
+ 	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
+-	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+-			  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
++	if (mtk_wed_is_v3_or_greater(dev->hw))
++		mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS,
++				  MTK_WED_WPDMA_STATUS_TX_DRV);
++	else
++		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++				  MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
+ 	mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
+ 
+ 	/* reset wed rx dma */
+@@ -1508,6 +1694,14 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 			  MTK_WED_CTRL_WED_RX_BM_BUSY);
+ 	mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
+ 
++	if (dev->wlan.hw_rro) {
++		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
++		mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++				  MTK_WED_CTRL_WED_RX_PG_BM_BUSY);
++		wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
++		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
++	}
++
+ 	/* wo change to enable state */
+ 	val = WO_STATE_ENABLE;
+ 	ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
+@@ -1527,6 +1721,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ 	}
+ 
+ 	mtk_wed_free_rx_buffer(dev);
++	mtk_wed_hwrro_free_buffer(dev);
+ 
+ 	return 0;
+ }
+@@ -1562,16 +1757,55 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 
+ 	/* 2. Reset WDMA Rx DMA/Driver_Engine */
+ 	busy = !!mtk_wdma_rx_reset(dev);
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		val = MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE |
++		      wed_r32(dev, MTK_WED_WDMA_GLO_CFG);
++		val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN;
++		wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val);
++	} else {
++		wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
++			MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
++	}
+ 
+-	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
+ 	if (!busy)
+ 		busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
+ 					 MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY);
++	if (!busy && mtk_wed_is_v3_or_greater(dev->hw))
++		busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
++					 MTK_WED_WDMA_RX_PREF_BUSY);
+ 
+ 	if (busy) {
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
+ 	} else {
++		if (mtk_wed_is_v3_or_greater(dev->hw)) {
++			/*1.a. Disable Prefetch HW*/
++			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++				MTK_WED_WDMA_RX_PREF_EN);
++			mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
++					  MTK_WED_WDMA_RX_PREF_BUSY);
++			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++				MTK_WED_WDMA_RX_PREF_DDONE2_EN);
++
++			/* reset prefetch index */
++			wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++				MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++				MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++			wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++				MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++				MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++			/* reset prefetch FIFO */
++			wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
++				MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
++				MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
++			wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
++
++			/*2. Reset dma index*/
++			wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
++				MTK_WED_WDMA_RESET_IDX_RX_ALL);
++		}
+ 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
+ 			MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV);
+ 		wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
+@@ -1587,8 +1821,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+ 
+ 	for (i = 0; i < 100; i++) {
+-		val = wed_r32(dev, MTK_WED_TX_BM_INTF);
+-		if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
++		if (mtk_wed_is_v1(dev->hw))
++			val = FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP,
++					wed_r32(dev, MTK_WED_TX_BM_INTF));
++		else
++			val = FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP,
++					wed_r32(dev, MTK_WED_TX_TKID_INTF));
++		if (val == 0x40)
+ 			break;
+ 	}
+ 
+@@ -1612,6 +1851,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
+ 		mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV);
++		if (mtk_wed_is_v3_or_greater(dev->hw))
++			wed_w32(dev, MTK_WED_RX1_CTRL2, 0);
+ 	} else {
+ 		wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
+ 			MTK_WED_WPDMA_RESET_IDX_TX |
+@@ -1628,7 +1869,14 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 		wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ 	}
+ 
+-	mtk_wed_rx_reset(dev);
++	if (mtk_wed_is_v3_or_greater(dev->hw)) {
++		/* reset amsdu engine */
++		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++		mtk_wed_reset(dev, MTK_WED_RESET_TX_AMSDU);
++	}
++
++	if (mtk_wed_get_rx_capa(dev))
++		mtk_wed_rx_reset(dev);
+ }
+ 
+ static int
+@@ -1945,7 +2193,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ }
+ 
+ static void
+-mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask, bool reset)
+ {
+ 	int i;
+ 
+@@ -1955,6 +2203,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
+ 	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
+ 		return;
+ 
++	if (reset) {
++		wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++			MTK_WED_RRO_MSDU_PG_DRV_EN);
++		return;
++	}
++
+ 	wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
+ 	wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
+ 		MTK_WED_RRO_MSDU_PG_DRV_CLR);
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+index 0af264d..1ee0fe1 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+@@ -36,6 +36,8 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RESET					0x008
+ #define MTK_WED_RESET_TX_BM				BIT(0)
+ #define MTK_WED_RESET_RX_BM				BIT(1)
++#define MTK_WED_RESET_RX_PG_BM				BIT(2)
++#define MTK_WED_RESET_RRO_RX_TO_PG			BIT(3)
+ #define MTK_WED_RESET_TX_FREE_AGENT			BIT(4)
+ #define MTK_WED_RESET_WPDMA_TX_DRV			BIT(8)
+ #define MTK_WED_RESET_WPDMA_RX_DRV			BIT(9)
+@@ -58,7 +60,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY		BIT(3)
+ #define MTK_WED_CTRL_WED_RX_IND_CMD_EN			BIT(5)
+ #define MTK_WED_CTRL_WED_RX_PG_BM_EN			BIT(6)
+-#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU			BIT(7)
++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY			BIT(7)
+ #define MTK_WED_CTRL_WED_TX_BM_EN			BIT(8)
+ #define MTK_WED_CTRL_WED_TX_BM_BUSY			BIT(9)
+ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN		BIT(10)
+@@ -117,6 +119,10 @@ struct mtk_wdma_desc {
+ #define MTK_WED_STATUS					0x060
+ #define MTK_WED_STATUS_TX				GENMASK(15, 8)
+ 
++#define MTK_WED_WPDMA_STATUS				0x068
++#define MTK_WED_WPDMA_STATUS_TX_DRV			GENMASK(15, 8)
++
++
+ #define MTK_WED_TX_BM_CTRL				0x080
+ #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM			GENMASK(6, 0)
+ #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM			GENMASK(22, 16)
+@@ -154,6 +160,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3		GENMASK(7, 0)
+ #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3		GENMASK(23, 16)
+ 
++#define MTK_WED_TX_TKID_INTF				0x0dc
++#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP		GENMASK(25, 16)
++
+ #define MTK_WED_TX_TKID_DYN_THR				0x0e0
+ #define MTK_WED_TX_TKID_DYN_THR_LO			GENMASK(6, 0)
+ #define MTK_WED_TX_TKID_DYN_THR_HI			GENMASK(22, 16)
+@@ -205,6 +214,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RING_RX_DATA(_n)			(0x420 + (_n) * 0x10)
+ 
+ #define MTK_WED_SCR0					0x3c0
++#define MTK_WED_RX1_CTRL2				0x418
+ #define MTK_WED_WPDMA_INT_TRIGGER			0x504
+ #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE		BIT(1)
+ #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE		GENMASK(5, 4)
+@@ -320,6 +330,7 @@ struct mtk_wdma_desc {
+ 
+ #define MTK_WED_WPDMA_RX_D_RST_IDX			0x760
+ #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX			GENMASK(17, 16)
++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL		BIT(20)
+ #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX			GENMASK(25, 24)
+ 
+ #define MTK_WED_WPDMA_RX_GLO_CFG			0x76c
+@@ -336,6 +347,7 @@ struct mtk_wdma_desc {
+ 
+ #define MTK_WED_WPDMA_RX_D_PREF_CFG			0x7b4
+ #define MTK_WED_WPDMA_RX_D_PREF_EN			BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_BUSY		BIT(1)
+ #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE		GENMASK(12, 8)
+ #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES		GENMASK(21, 16)
+ 
+@@ -357,11 +369,13 @@ struct mtk_wdma_desc {
+ 
+ #define MTK_WED_WDMA_RX_PREF_CFG			0x950
+ #define MTK_WED_WDMA_RX_PREF_EN				BIT(0)
++#define MTK_WED_WDMA_RX_PREF_BUSY			BIT(1)
+ #define MTK_WED_WDMA_RX_PREF_BURST_SIZE			GENMASK(12, 8)
+ #define MTK_WED_WDMA_RX_PREF_LOW_THRES			GENMASK(21, 16)
+ #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR		BIT(24)
+ #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR		BIT(25)
+ #define MTK_WED_WDMA_RX_PREF_DDONE2_EN			BIT(26)
++#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY		BIT(27)
+ 
+ #define MTK_WED_WDMA_RX_PREF_FIFO_CFG			0x95C
+ #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR		BIT(0)
+@@ -390,6 +404,7 @@ struct mtk_wdma_desc {
+ 
+ #define MTK_WED_WDMA_RESET_IDX				0xa08
+ #define MTK_WED_WDMA_RESET_IDX_RX			GENMASK(17, 16)
++#define MTK_WED_WDMA_RESET_IDX_RX_ALL			BIT(20)
+ #define MTK_WED_WDMA_RESET_IDX_DRV			GENMASK(25, 24)
+ 
+ #define MTK_WED_WDMA_INT_CLR				0xa24
+@@ -458,21 +473,66 @@ struct mtk_wdma_desc {
+ #define MTK_WDMA_INT_MASK_RX_DELAY			BIT(30)
+ #define MTK_WDMA_INT_MASK_RX_COHERENT			BIT(31)
+ 
++#define MTK_WDMA_XDMA_TX_FIFO_CFG			0x238
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR		BIT(0)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR		BIT(4)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR		BIT(8)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR		BIT(12)
++
++#define MTK_WDMA_XDMA_RX_FIFO_CFG			0x23c
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR		BIT(0)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR		BIT(4)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR		BIT(8)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR		BIT(12)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR		BIT(15)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR		BIT(18)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR		BIT(21)
++
++
++
+ #define MTK_WDMA_INT_GRP1				0x250
+ #define MTK_WDMA_INT_GRP2				0x254
+ 
+ #define MTK_WDMA_PREF_TX_CFG				0x2d0
+ #define MTK_WDMA_PREF_TX_CFG_PREF_EN			BIT(0)
++#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY			BIT(1)
+ 
+ #define MTK_WDMA_PREF_RX_CFG				0x2dc
+ #define MTK_WDMA_PREF_RX_CFG_PREF_EN			BIT(0)
++#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY			BIT(1)
++
++#define MTK_WDMA_PREF_RX_FIFO_CFG			0x2e0
++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR		BIT(0)
++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR		BIT(16)
++
++#define MTK_WDMA_PREF_TX_FIFO_CFG			0x2d4
++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR		BIT(0)
++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR		BIT(16)
++
++#define MTK_WDMA_PREF_SIDX_CFG				0x2e4
++#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
++#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
+ 
+ #define MTK_WDMA_WRBK_TX_CFG				0x300
++#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY			BIT(0)
+ #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN			BIT(30)
+ 
++#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n)			(0x304 + (_n) * 0x4)
++#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR		BIT(0)
++
++
+ #define MTK_WDMA_WRBK_RX_CFG				0x344
++#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY			BIT(0)
+ #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN			BIT(30)
+ 
++#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n)			(0x348 + (_n) * 0x4)
++#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR		BIT(0)
++
++
++#define MTK_WDMA_WRBK_SIDX_CFG				0x388
++#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR		GENMASK(3, 0)
++#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR		GENMASK(5, 4)
++
+ #define MTK_PCIE_MIRROR_MAP(n)				((n) ? 0x4 : 0x0)
+ #define MTK_PCIE_MIRROR_MAP_EN				BIT(0)
+ #define MTK_PCIE_MIRROR_MAP_WED_ID			BIT(1)
+@@ -486,6 +546,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RTQM_Q_DBG_BYPASS			BIT(5)
+ #define MTK_WED_RTQM_TXDMAD_FPORT			GENMASK(23, 20)
+ 
++#define MTK_WED_RTQM_RST				0xb04
++
++
+ #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT		0xb1c
+ #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n)		(0xb20 + (_n) * 0x4)
+ #define	MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT			0xb28
+@@ -675,6 +738,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR		BIT(17)
+ #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG	GENMASK(22, 18)
+ 
++#define MTK_WED_RRO_RX_HW_STS				0xf00
++#define MTK_WED_RX_IND_CMD_BUSY			GENMASK(31, 0)
++
+ #define MTK_WED_RX_IND_CMD_CNT0				0xf20
+ #define MTK_WED_RX_IND_CMD_DBG_CNT_EN			BIT(31)
+ 
+diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
+index e81e41f..83a4b8b 100644
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -222,7 +222,7 @@ struct mtk_wed_ops {
+ 
+ 	u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
+-	void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask);
++	void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask, bool reset);
+ 	void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
+ 				  void __iomem *regs);
+ 	void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
+@@ -302,8 +302,8 @@ mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
+ 	(_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
+-#define mtk_wed_device_start_hw_rro(_dev, _mask) \
+-	(_dev)->ops->start_hw_rro(_dev, _mask)
++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) \
++	(_dev)->ops->start_hw_rro(_dev, _mask, _reset)
+ #define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
+ 	(_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
+ #define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
+@@ -329,7 +329,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_stop(_dev) do {} while (0)
+ #define mtk_wed_device_dma_reset(_dev) do {} while (0)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
+-#define mtk_wed_device_start_hw_rro(_dev, _mask) do {} while (0)
++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) do {} while (0)
+ #define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
+ #define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs)  -ENODEV
+ #define mtk_wed_device_ind_rx_ring_setup(_dev, _regs)  -ENODEV
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
similarity index 78%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
rename to autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
index af32459..0d0ac4e 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
@@ -1,7 +1,7 @@
-From 659d8d088ee856cbc7598a26a307fd3e20a70e8e Mon Sep 17 00:00:00 2001
+From a0aa9757876b525b24a16bd3cb48b5dac02a8945 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 13:23:56 +0800
-Subject: [PATCH 22/22] mtk: wed: add dma mask limitation and GFP_DMA32 for
+Subject: [PATCH 21/24] mtk: wed: add dma mask limitation and GFP_DMA32 for
  board >= 4GB dram
 
 ---
@@ -12,10 +12,10 @@
  4 files changed, 11 insertions(+), 6 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 0d101d5..2ec7148 100644
+index 7f14d43..b928ff6 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -472,7 +472,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+@@ -638,7 +638,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
  		void *buf;
  		int s;
  
@@ -24,7 +24,7 @@
  		if (!page)
  			return -ENOMEM;
  
-@@ -636,7 +636,7 @@ mtk_wed_rx_page_buffer_alloc(struct mtk_wed_device *dev)
+@@ -762,7 +762,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev)
  		void *buf;
  		int s;
  
@@ -33,22 +33,22 @@
  		if (!page)
  			return -ENOMEM;
  
-@@ -2249,6 +2249,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- 	dev->wdma_idx = hw->index;
- 	dev->ver = hw->version;
+@@ -2464,6 +2464,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ 	dev->version = hw->version;
+ 	dev->hw->pci_base = mtk_wed_get_pci_base(dev);
  
 +	ret = dma_set_mask_and_coherent(hw->dev, DMA_BIT_MASK(32));
 +	if (ret)
 +		return ret;
 +
- 	if (dev->hw->version == 3)
- 		dev->hw->pci_base = mtk_wed_get_pci_base(dev);
- 
+ 	if (hw->eth->dma_dev == hw->eth->dev &&
+ 	    of_dma_is_coherent(hw->eth->dev->of_node))
+ 		mtk_eth_set_dma_device(hw->eth, hw->dev);
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-index 055594d..4ed1548 100644
+index 18d1fb1..a88061c 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -131,7 +131,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
+@@ -145,7 +145,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
  	}req;
  
  	exp->log_size = EXCEPTION_LOG_SIZE;
@@ -57,7 +57,7 @@
  	if (!exp->log)
  		return -ENOMEM;
  
-@@ -151,7 +151,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
+@@ -165,7 +165,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
  				    &req, sizeof(req), false);
  
  free:
@@ -89,7 +89,7 @@
  
  	wo->hw = NULL;
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-index 548b38e..3fd1f3f 100644
+index b24fef3..5afa6de 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h
 +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
 @@ -193,6 +193,7 @@ struct mtk_wed_wo {
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
similarity index 83%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
rename to autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
index cd6c8ca..15d51b9 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
@@ -1,7 +1,8 @@
-From f80b9b330efd9d675c7c548c5af459792037ca99 Mon Sep 17 00:00:00 2001
+From d73ee12c93d4146b3585fc5d93271b1fbafcd3c4 Mon Sep 17 00:00:00 2001
 From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
 Date: Tue, 26 Dec 2023 16:46:16 +0800
-Subject: [PATCH] 999-3022-mediatek-ethernet-add-multiple-ppe-allocatiion.patch
+Subject: [PATCH 22/24] 
+ 999-3022-mediatek-ethernet-add-multiple-ppe-allocatiion.patch
 
 ---
  arch/arm64/boot/dts/mediatek/mt7988.dtsi      |  1 +
@@ -11,10 +12,10 @@
  4 files changed, 31 insertions(+), 2 deletions(-)
 
 diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-index 44a2f1b..cf50542 100644
+index 3368240..ff1619d 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
 +++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-@@ -949,6 +949,7 @@
+@@ -945,6 +945,7 @@
  		mediatek,infracfg = <&topmisc>;
  		mediatek,toprgu = <&watchdog>;
  		mediatek,hwver = <&hwver>;
@@ -23,10 +24,10 @@
  		#address-cells = <1>;
  		#size-cells = <0>;
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 4cdfead..9009960 100644
+index a3ed175..a761d95 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2170,6 +2170,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2349,6 +2349,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  	u8 *data, *new_data;
  	struct mtk_rx_dma_v2 *rxd, trxd;
  	int done = 0;
@@ -34,7 +35,7 @@
  
  	if (unlikely(!ring))
  		goto rx_done;
-@@ -2277,7 +2278,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2460,7 +2461,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
  		reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
  		if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
@@ -44,7 +45,7 @@
  					  trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2);
  		}
  #else
-@@ -3781,7 +3783,19 @@ static int mtk_open(struct net_device *dev)
+@@ -4114,7 +4116,19 @@ static int mtk_open(struct net_device *dev)
  			     SGMSYS_QPHY_PWR_STATE_CTRL, 0);
  
  	if (eth->soc->offload_version) {
@@ -65,7 +66,7 @@
  
  			for (i = 0; i < eth->ppe_num; i++)
  				mtk_ppe_start(eth->ppe[i]);
-@@ -4748,6 +4762,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+@@ -5130,6 +5144,7 @@ static const struct net_device_ops mtk_netdev_ops = {
  	.ndo_poll_controller	= mtk_poll_controller,
  #endif
  	.ndo_setup_tc		= mtk_eth_setup_tc,
@@ -74,10 +75,10 @@
  
  static void mux_poll(struct work_struct *work)
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 12ffb3c..1bf335c 100644
+index 88d2f46..711a8e9 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1945,6 +1945,7 @@ struct mtk_mac {
+@@ -1973,6 +1973,7 @@ struct mtk_mac {
  	phy_interface_t			interface;
  	unsigned int			mode;
  	unsigned int			type;
@@ -85,7 +86,7 @@
  	int				speed;
  	struct device_node		*of_node;
  	struct phylink			*phylink;
-@@ -2045,6 +2046,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -2074,6 +2075,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
  		     void *type_data);
  int mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f,
  			   struct mtk_eth *eth);
@@ -95,10 +96,10 @@
  u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
  
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-index 339359e..8f721ba 100644
+index 2d432f2..7f432be 100644
 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -693,6 +693,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -694,6 +694,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
  	}
  }
  
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
similarity index 88%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
rename to autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
index 31d8b89..92591a5 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
@@ -1,14 +1,15 @@
-From 8306aa4c52abf96af2c229762207369f279c89e2 Mon Sep 17 00:00:00 2001
+From e8a6054c824c5c65abd501bfd7437a3d7c5f2751 Mon Sep 17 00:00:00 2001
 From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
 Date: Tue, 28 Nov 2023 13:25:03 +0800
-Subject: [PATCH] 999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ
+Subject: [PATCH 23/24] 
+ mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ
 
 ---
  drivers/net/ethernet/mediatek/mtk_ppe.c | 27 +++++++++++++++++++++++++
  1 file changed, 27 insertions(+)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 16aec2e..1e2b96e 100644
+index ae0acd5..84d9763 100644
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -451,6 +451,28 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3025-dts-88d-option-type-2-support.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3024-dts-88d-option-type-2-support.patch
similarity index 83%
rename from autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3025-dts-88d-option-type-2-support.patch
rename to autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3024-dts-88d-option-type-2-support.patch
index 9084982..9125b94 100644
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/target/linux/mediatek/patches-5.4/999-3025-dts-88d-option-type-2-support.patch
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/999-3024-dts-88d-option-type-2-support.patch
@@ -1,7 +1,7 @@
-From a344727c9d91c162839e7283aeac281f88f30e8a Mon Sep 17 00:00:00 2001
+From b294202119468041b6f4b6651f968c9d2a0adcc2 Mon Sep 17 00:00:00 2001
 From: Rex Lu <rex.lu@mediatek.com>
 Date: Mon, 22 Jan 2024 13:50:29 +0800
-Subject: [PATCH] dts 88d option type 2 support
+Subject: [PATCH 24/24] dts 88d option type 2 support
 
 Signed-off-by: Rex Lu <rex.lu@mediatek.com>
 ---
@@ -10,10 +10,10 @@
  2 files changed, 2 insertions(+)
 
 diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
-index 5513d04..7619009 100644
+index 8ebcbaf..df15051 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
 +++ b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
-@@ -569,6 +569,7 @@
+@@ -572,6 +572,7 @@
  	mt7996@0,0 {
  		reg = <0x0000 0 0 0 0>;
  		device_type = "pci";
@@ -22,10 +22,10 @@
  	};
  };
 diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
-index 4cab1ae..b98efb9 100644
+index d4f96c8..c27ffa6 100644
 --- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
 +++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
-@@ -546,6 +546,7 @@
+@@ -547,6 +547,7 @@
  	mt7996@0,0 {
  		reg = <0x0000 0 0 0 0>;
  		device_type = "pci";