Merge "[AUTO00246924][rdkb][common][app][add uci cmd for he_bss_color, transmit_power]"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
deleted file mode 100644
index 3292a6b..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 051e070d0a019df6be9e21be1fb63352e4c4412e Mon Sep 17 00:00:00 2001
-From: YouChing Lin <ycllin@mxic.com.tw>
-Date: Wed, 22 Jul 2020 16:02:57 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add support for MX31LF1GE4BC
-
-The Macronix MX31LF1GE4BC is a 3V, 1Gbit (128MB) serial
-NAND flash device.
-
-Validated by read, erase, read back, write and read back
-on Xilinx Zynq PicoZed FPGA board which included
-Macronix SPI Host (driver/spi/spi-mxic.c).
-
-Signed-off-by: YouChing Lin <ycllin@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1595404978-31079-2-git-send-email-ycllin@mxic.com.tw
----
- drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 9ff8debd599418..9ae48ce1c46f91 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -119,6 +119,16 @@ static const struct spinand_info macronix_spinand_table[] = {
- 					      &update_cache_variants),
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
-+	SPINAND_INFO("MX31LF1GE4BC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/431-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/431-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
deleted file mode 100644
index 9f48d4a..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/431-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 75b049bb7f89a58a25592f17baf91d703f0f548e Mon Sep 17 00:00:00 2001
-From: YouChing Lin <ycllin@mxic.com.tw>
-Date: Wed, 22 Jul 2020 16:02:58 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add support for MX31UF1GE4BC
-
-The Macronix MX31UF1GE4BC is a 1.8V, 1Gbit (128MB) serial
-NAND flash device.
-
-Validated by read, erase, read back, write and read back
-on Xilinx Zynq PicoZed FPGA board which included
-Macronix SPI Host (driver/spi/spi-mxic.c).
-
-Signed-off-by: YouChing Lin <ycllin@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1595404978-31079-3-git-send-email-ycllin@mxic.com.tw
----
- drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 9ae48ce1c46f91..8e801e4c3a006f 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -129,6 +129,16 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     0 /*SPINAND_HAS_QE_BIT*/,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX31UF1GE4BC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/451-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/451-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
deleted file mode 100644
index 31141db..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/451-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 8511a3a9937e30949b34bea46c3dc3f65d11034b Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:31 +0100
-Subject: [PATCH] mtd: spinand: micron: Describe the SPI NAND device
- MT29F2G01ABAGD
-
-Add the SPI NAND device MT29F2G01ABAGD series number, size and voltage
-details as a comment.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-3-sshivamurthy@micron.com
----
- drivers/mtd/nand/spi/micron.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index cc1ee68421c8e1..4727933c894bc8 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -91,6 +91,7 @@ static int micron_8_ecc_get_status(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info micron_spinand_table[] = {
-+	/* M79A 2Gb 3.3V */
- 	SPINAND_INFO("MT29F2G01ABAGD",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/453-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/453-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
deleted file mode 100644
index 59a4234..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/453-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From 0bc68af9137dc3f30b161de4ce546c7799f88d1e Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:33 +0100
-Subject: [PATCH] mtd: spinand: micron: identify SPI NAND device with
- Continuous Read mode
-
-Add SPINAND_HAS_CR_FEAT_BIT flag to identify the SPI NAND device with
-the Continuous Read mode.
-
-Some of the Micron SPI NAND devices have the "Continuous Read" feature
-enabled by default, which does not fit the subsystem needs.
-
-In this mode, the READ CACHE command doesn't require the starting column
-address. The device always output the data starting from the first
-column of the cache register, and once the end of the cache register
-reached, the data output continues through the next page. With the
-continuous read mode, it is possible to read out the entire block using
-a single READ command, and once the end of the block reached, the output
-pins become High-Z state. However, during this mode the read command
-doesn't output the OOB area.
-
-Hence, we disable the feature at probe time.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-5-sshivamurthy@micron.com
----
- drivers/mtd/nand/spi/micron.c | 16 ++++++++++++++++
- include/linux/mtd/spinand.h   |  1 +
- 2 files changed, 17 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 26925714a9fbac..956f7710aca263 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -18,6 +18,8 @@
- #define MICRON_STATUS_ECC_4TO6_BITFLIPS	(3 << 4)
- #define MICRON_STATUS_ECC_7TO8_BITFLIPS	(5 << 4)
- 
-+#define MICRON_CFG_CR			BIT(0)
-+
- static SPINAND_OP_VARIANTS(read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-@@ -137,7 +139,21 @@ static const struct spinand_info micron_spinand_table[] = {
- 				     micron_8_ecc_get_status)),
- };
- 
-+static int micron_spinand_init(struct spinand_device *spinand)
-+{
-+	/*
-+	 * M70A device series enable Continuous Read feature at Power-up,
-+	 * which is not supported. Disable this bit to avoid any possible
-+	 * failure.
-+	 */
-+	if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT)
-+		return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0);
-+
-+	return 0;
-+}
-+
- static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
-+	.init = micron_spinand_init,
- };
- 
- const struct spinand_manufacturer micron_spinand_manufacturer = {
-diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
-index f4c4ae87181b27..1077c45721ff25 100644
---- a/include/linux/mtd/spinand.h
-+++ b/include/linux/mtd/spinand.h
-@@ -284,6 +284,7 @@ struct spinand_ecc_info {
- };
- 
- #define SPINAND_HAS_QE_BIT		BIT(0)
-+#define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
- 
- /**
-  * struct spinand_info - Structure used to describe SPI NAND chips
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
deleted file mode 100644
index 26de067..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
+++ /dev/null
@@ -1,269 +0,0 @@
-From patchwork Mon Mar 23 15:05:51 2020
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Dejin Zheng <zhengdejin5@gmail.com>
-X-Patchwork-Id: 1260097
-X-Patchwork-Delegate: davem@davemloft.net
-Return-Path: <netdev-owner@vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev@ozlabs.org
-Delivered-To: patchwork-incoming-netdev@ozlabs.org
-Authentication-Results: ozlabs.org; spf=none (no SPF record)
-	smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67;
-	helo=vger.kernel.org;
-	envelope-from=netdev-owner@vger.kernel.org;
-	receiver=<UNKNOWN>)
-Authentication-Results: ozlabs.org;
-	dmarc=pass (p=none dis=none) header.from=gmail.com
-Authentication-Results: ozlabs.org; dkim=pass (2048-bit key;
-	unprotected) header.d=gmail.com header.i=@gmail.com
-	header.a=rsa-sha256 header.s=20161025 header.b=N1ACwCYl;
-	dkim-atps=neutral
-Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
-	by ozlabs.org (Postfix) with ESMTP id 48mHlP3Hzhz9sSs
-	for <patchwork-incoming-netdev@ozlabs.org>;
-	Tue, 24 Mar 2020 02:06:25 +1100 (AEDT)
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
-	id S1727267AbgCWPGW (ORCPT
-	<rfc822;patchwork-incoming-netdev@ozlabs.org>);
-	Mon, 23 Mar 2020 11:06:22 -0400
-Received: from mail-pj1-f68.google.com ([209.85.216.68]:50286 "EHLO
-	mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
-	with ESMTP id S1727024AbgCWPGV (ORCPT
-	<rfc822;netdev@vger.kernel.org>); Mon, 23 Mar 2020 11:06:21 -0400
-Received: by mail-pj1-f68.google.com with SMTP id v13so6312358pjb.0;
-	Mon, 23 Mar 2020 08:06:20 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
-	d=gmail.com; s=20161025;
-	h=from:to:cc:subject:date:message-id:in-reply-to:references
-	:mime-version:content-transfer-encoding;
-	bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=;
-	b=N1ACwCYlon7WkTCOGFsGWeQq6lNeUjbuQa8UGIBK7O82wFqYoTVzGY8MUnU/tEjer9
-	AtZt9996i6pDsvhpbunlFffuKPui1YOisSe6Xcn6Ur2AiFvfJr1DMpWE2PdmlLGH2bkH
-	/Oiqbikpi9dSUfgFJ7JfIyISqKyP15jsdhhl8xtA30gWb6CuhlhBuWuLV5CqTAZKGWab
-	LMFipg2GDKlx0udJoUoNAPi/hcypdWJW8DtamDxwH/OmZk2evJsfhm2MwG/1qAb95nJ0
-	rU/60e4BhqadPHfO9cyvgdbR+xcCJkuSIqKWH6utfd9RamZDS2djU3XDWhFW2blmcVLb
-	Ue5w==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
-	d=1e100.net; s=20161025;
-	h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
-	:references:mime-version:content-transfer-encoding;
-	bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=;
-	b=AwMmzIpdEKD6duSw3Dl9aQkzxRMmPOysumBp0nIE9FvhZJ+67auGBvMa7G80/DyF4x
-	BbrwsUrYoDLXs7fuLEjjZgxKwSCtYfWyPDdM/ezShIx9KZIfPiXhn6uH3eXP+g4feJN4
-	IlWVwvJMDzRJOhdZVzg934FJeMs4bW7XNm07jKxjsqksHGcw5JoHsP53xNegPbIpNb8X
-	h7+AwHXYAKzVC9aGYTA8bgxSD0d+SlO7CJ4nY+lHXcBR266/rt7rDFOwCdv9TUUAMCkY
-	rXrgSb8vThpKY/wZ8rK3SyJcPdvDt6TnmdZO7LqTbbzAHjzJml7s+5vYhk3CSOvjGTHt
-	KcMA==
-X-Gm-Message-State: ANhLgQ1lOBl50y5dc6fz/BIFJrpgXnM0GF/1DvoZm8oJbZIt2H9n38WA
-	pBi6LVse2n2Ed5tvz68N8x8=
-X-Google-Smtp-Source: 
- ADFU+vtPoQt/0UFiy7Bq0L9uIMvQbBOJzH8+jTojBCcjj2V26XqJvxqSMSsy9g8ZZ96F/Q8I4cpXYw==
-X-Received: by 2002:a17:902:9a09:: with SMTP id
-	v9mr21358610plp.341.1584975980336;
-	Mon, 23 Mar 2020 08:06:20 -0700 (PDT)
-Received: from localhost (176.122.158.203.16clouds.com. [176.122.158.203])
-	by smtp.gmail.com with ESMTPSA id
-	j19sm13485589pfe.102.2020.03.23.08.06.19
-	(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
-	Mon, 23 Mar 2020 08:06:19 -0700 (PDT)
-From: Dejin Zheng <zhengdejin5@gmail.com>
-To: andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com,
-	linux@armlinux.org.uk, davem@davemloft.net, corbet@lwn.net,
-	tglx@linutronix.de, gregkh@linuxfoundation.org,
-	allison@lohutok.net, mchehab+samsung@kernel.org, netdev@vger.kernel.org
-Cc: linux-kernel@vger.kernel.org, Dejin Zheng <zhengdejin5@gmail.com>
-Subject: [PATCH net-next v7 01/10] iopoll: introduce read_poll_timeout macro
-Date: Mon, 23 Mar 2020 23:05:51 +0800
-Message-Id: <20200323150600.21382-2-zhengdejin5@gmail.com>
-X-Mailer: git-send-email 2.25.0
-In-Reply-To: <20200323150600.21382-1-zhengdejin5@gmail.com>
-References: <20200323150600.21382-1-zhengdejin5@gmail.com>
-MIME-Version: 1.0
-Sender: netdev-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev@vger.kernel.org
-
-this macro is an extension of readx_poll_timeout macro. the accessor
-function op just supports only one parameter in the readx_poll_timeout
-macro, but this macro can supports multiple variable parameters for
-it. so functions like phy_read(struct phy_device *phydev, u32 regnum)
-and phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) can
-also use this poll timeout core. and also expand it can sleep some time
-before read operation.
-
-Signed-off-by: Dejin Zheng <zhengdejin5@gmail.com>
----
-v6 -> v7:
-	- add a parameter sleep_before_read to support that it can sleep
-	  some time before read operation in read_poll_timeout macro.
-v5 -> v6:
-	- no changed
-v4 -> v5:
-	- no changed
-v3 -> v4:
-	- no changed
-v2 -> v3:
-	- no changed
-v1 -> v2:
-	- no changed
-
- include/linux/iopoll.h | 44 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 44 insertions(+)
-
---- a/include/linux/iopoll.h
-+++ b/include/linux/iopoll.h
-@@ -14,36 +14,41 @@
- #include <linux/io.h>
- 
- /**
-- * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
-- * @op: accessor function (takes @addr as its only argument)
-- * @addr: Address to poll
-+ * read_poll_timeout - Periodically poll an address until a condition is
-+ *			met or a timeout occurs
-+ * @op: accessor function (takes @args as its arguments)
-  * @val: Variable to read the value into
-  * @cond: Break condition (usually involving @val)
-  * @sleep_us: Maximum time to sleep between reads in us (0
-  *            tight-loops).  Should be less than ~20ms since usleep_range
-  *            is used (see Documentation/timers/timers-howto.rst).
-  * @timeout_us: Timeout in us, 0 means never timeout
-+ * @sleep_before_read: if it is true, sleep @sleep_us before read.
-+ * @args: arguments for @op poll
-  *
-  * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-- * case, the last read value at @addr is stored in @val. Must not
-+ * case, the last read value at @args is stored in @val. Must not
-  * be called from atomic context if sleep_us or timeout_us are used.
-  *
-  * When available, you'll probably want to use one of the specialized
-  * macros defined below rather than this macro directly.
-  */
--#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)	\
-+#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
-+				sleep_before_read, args...) \
- ({ \
- 	u64 __timeout_us = (timeout_us); \
- 	unsigned long __sleep_us = (sleep_us); \
- 	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
- 	might_sleep_if((__sleep_us) != 0); \
-+	if (sleep_before_read && __sleep_us) \
-+		usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
- 	for (;;) { \
--		(val) = op(addr); \
-+		(val) = op(args); \
- 		if (cond) \
- 			break; \
- 		if (__timeout_us && \
- 		    ktime_compare(ktime_get(), __timeout) > 0) { \
--			(val) = op(addr); \
-+			(val) = op(args); \
- 			break; \
- 		} \
- 		if (__sleep_us) \
-@@ -53,6 +58,27 @@
- })
- 
- /**
-+ * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
-+ * @op: accessor function (takes @addr as its only argument)
-+ * @addr: Address to poll
-+ * @val: Variable to read the value into
-+ * @cond: Break condition (usually involving @val)
-+ * @sleep_us: Maximum time to sleep between reads in us (0
-+ *            tight-loops).  Should be less than ~20ms since usleep_range
-+ *            is used (see Documentation/timers/timers-howto.rst).
-+ * @timeout_us: Timeout in us, 0 means never timeout
-+ *
-+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-+ * case, the last read value at @addr is stored in @val. Must not
-+ * be called from atomic context if sleep_us or timeout_us are used.
-+ *
-+ * When available, you'll probably want to use one of the specialized
-+ * macros defined below rather than this macro directly.
-+ */
-+#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)	\
-+	read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
-+
-+/**
-  * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs
-  * @op: accessor function (takes @addr as its only argument)
-  * @addr: Address to poll
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -21,6 +21,7 @@
- #include <linux/timer.h>
- #include <linux/workqueue.h>
- #include <linux/mod_devicetable.h>
-+#include <linux/iopoll.h>
- 
- #include <linux/atomic.h>
- 
-@@ -714,6 +715,19 @@ static inline int phy_read(struct phy_de
- 	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
- }
- 
-+#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
-+				timeout_us, sleep_before_read) \
-+({ \
-+	int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \
-+		sleep_us, timeout_us, sleep_before_read, phydev, regnum); \
-+	if (val <  0) \
-+		__ret = val; \
-+	if (__ret) \
-+		phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
-+	__ret; \
-+})
-+
-+
- /**
-  * __phy_read - convenience function for reading a given PHY register
-  * @phydev: the phy_device struct
-@@ -766,6 +780,19 @@ static inline int __phy_write(struct phy
-  */
- int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
- 
-+#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
-+				  sleep_us, timeout_us, sleep_before_read) \
-+({ \
-+	int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
-+				  sleep_us, timeout_us, sleep_before_read, \
-+				  phydev, devaddr, regnum); \
-+	if (val <  0) \
-+		__ret = val; \
-+	if (__ret) \
-+		phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
-+	__ret; \
-+})
-+
- /**
-  * __phy_read_mmd - Convenience function for reading a register
-  * from an MMD on a given PHY.
---- a/drivers/net/phy/phy_device.c
-+++ b/drivers/net/phy/phy_device.c
-@@ -1056,18 +1056,12 @@ EXPORT_SYMBOL(phy_disconnect);
- static int phy_poll_reset(struct phy_device *phydev)
- {
- 	/* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
--	unsigned int retries = 12;
--	int ret;
--
--	do {
--		msleep(50);
--		ret = phy_read(phydev, MII_BMCR);
--		if (ret < 0)
--			return ret;
--	} while (ret & BMCR_RESET && --retries);
--	if (ret & BMCR_RESET)
--		return -ETIMEDOUT;
-+	int ret, val;
- 
-+	ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
-+				    50000, 600000, true);
-+	if (ret)
-+		return ret;
- 	/* Some chips (smsc911x) may still need up to another 1ms after the
- 	 * BMCR_RESET bit is cleared before they are usable.
- 	 */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
deleted file mode 100644
index 39b29ad..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From patchwork Tue Jun 23 14:30:07 2020
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Antoine Tenart <antoine.tenart@bootlin.com>
-X-Patchwork-Id: 1315292
-X-Patchwork-Delegate: davem@davemloft.net
-Return-Path: <netdev-owner@vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev@ozlabs.org
-Delivered-To: patchwork-incoming-netdev@ozlabs.org
-Authentication-Results: ozlabs.org;
- spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
- (client-ip=23.128.96.18; helo=vger.kernel.org;
- envelope-from=netdev-owner@vger.kernel.org; receiver=<UNKNOWN>)
-Authentication-Results: ozlabs.org;
- dmarc=none (p=none dis=none) header.from=bootlin.com
-Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
-	by ozlabs.org (Postfix) with ESMTP id 49rpjP0BTdz9sRN
-	for <patchwork-incoming-netdev@ozlabs.org>;
- Wed, 24 Jun 2020 00:35:37 +1000 (AEST)
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
-        id S1732957AbgFWOf1 (ORCPT
-        <rfc822;patchwork-incoming-netdev@ozlabs.org>);
-        Tue, 23 Jun 2020 10:35:27 -0400
-Received: from relay3-d.mail.gandi.net ([217.70.183.195]:35381 "EHLO
-        relay3-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
-        with ESMTP id S1732900AbgFWOfX (ORCPT
-        <rfc822;netdev@vger.kernel.org>); Tue, 23 Jun 2020 10:35:23 -0400
-X-Originating-IP: 90.76.143.236
-Received: from localhost (lfbn-tou-1-1075-236.w90-76.abo.wanadoo.fr
- [90.76.143.236])
-        (Authenticated sender: antoine.tenart@bootlin.com)
-        by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 38BE860006;
-        Tue, 23 Jun 2020 14:35:19 +0000 (UTC)
-From: Antoine Tenart <antoine.tenart@bootlin.com>
-To: davem@davemloft.net, andrew@lunn.ch, f.fainelli@gmail.com,
-        hkallweit1@gmail.com, richardcochran@gmail.com,
-        alexandre.belloni@bootlin.com, UNGLinuxDriver@microchip.com
-Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
-        thomas.petazzoni@bootlin.com, allan.nielsen@microchip.com,
-        foss@0leil.net, antoine.tenart@bootlin.com
-Subject: [PATCH net-next v4 1/8] net: phy: add support for a common probe
- between shared PHYs
-Date: Tue, 23 Jun 2020 16:30:07 +0200
-Message-Id: <20200623143014.47864-2-antoine.tenart@bootlin.com>
-X-Mailer: git-send-email 2.26.2
-In-Reply-To: <20200623143014.47864-1-antoine.tenart@bootlin.com>
-References: <20200623143014.47864-1-antoine.tenart@bootlin.com>
-MIME-Version: 1.0
-Sender: netdev-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev@vger.kernel.org
-
-Shared PHYs (PHYs in the same hardware package) may have shared
-registers and their drivers would usually need to share information.
-There is currently a way to have a shared (part of the) init, by using
-phy_package_init_once(). This patch extends the logic to share parts of
-the probe to allow sharing the initialization of locks or resources
-retrieval.
-
-Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
----
- include/linux/phy.h | 18 +++++++++++++++---
- 1 file changed, 15 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/phy.h b/include/linux/phy.h
-index 9248dd2ce4ca..457489f1951c 100644
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -244,7 +244,8 @@ struct phy_package_shared {
- };
- 
- /* used as bit number in atomic bitops */
--#define PHY_SHARED_F_INIT_DONE 0
-+#define PHY_SHARED_F_INIT_DONE  0
-+#define PHY_SHARED_F_PROBE_DONE 1
- 
- /*
-  * The Bus class for PHYs.  Devices which provide access to
-@@ -1558,14 +1559,25 @@ static inline int __phy_package_write(struct phy_device *phydev,
- 	return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
- }
- 
--static inline bool phy_package_init_once(struct phy_device *phydev)
-+static inline bool __phy_package_set_once(struct phy_device *phydev,
-+					  unsigned int b)
- {
- 	struct phy_package_shared *shared = phydev->shared;
- 
- 	if (!shared)
- 		return false;
- 
--	return !test_and_set_bit(PHY_SHARED_F_INIT_DONE, &shared->flags);
-+	return !test_and_set_bit(b, &shared->flags);
-+}
-+
-+static inline bool phy_package_init_once(struct phy_device *phydev)
-+{
-+	return __phy_package_set_once(phydev, PHY_SHARED_F_INIT_DONE);
-+}
-+
-+static inline bool phy_package_probe_once(struct phy_device *phydev)
-+{
-+	return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE);
- }
- 
- extern struct bus_type mdio_bus_type;
\ No newline at end of file
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2210-v6.1-iio-adc-add-rtq6056-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2210-v6.1-iio-adc-add-rtq6056-support.patch
new file mode 100644
index 0000000..ce35b7a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2210-v6.1-iio-adc-add-rtq6056-support.patch
@@ -0,0 +1,708 @@
+From 37b0b79827edbd5c312aa546a1fe148bda616e30 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Wed, 31 May 2023 19:53:09 +0800
+Subject: [PATCH] iio: adc: Add rtq6056 support
+
+---
+ drivers/iio/adc/Kconfig   |  15 +
+ drivers/iio/adc/Makefile  |   1 +
+ drivers/iio/adc/rtq6056.c | 649 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 665 insertions(+)
+ create mode 100644 drivers/iio/adc/rtq6056.c
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index cb57880..7457a53 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -746,6 +746,21 @@ config ROCKCHIP_SARADC
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called rockchip_saradc.
+ 
++config RICHTEK_RTQ6056
++	tristate "Richtek RTQ6056 Current and Power Monitor ADC"
++	depends on I2C
++	select REGMAP_I2C
++	select IIO_BUFFER
++	select IIO_TRIGGERED_BUFFER
++	help
++	  Say yes here to enable RQT6056 ADC support.
++	  RTQ6056 is a high accuracy current-sense monitor with I2C and SMBus
++	  compatible interface, and the device provides full information for
++	  system by reading out the load current and power.
++
++	  This driver can also be built as a module. If so, the module will be
++	  called rtq6056.
++
+ config SC27XX_ADC
+ 	tristate "Spreadtrum SC27xx series PMICs ADC"
+ 	depends on MFD_SC27XX_PMIC || COMPILE_TEST
+diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
+index ef9cc48..6a4ac1b 100644
+--- a/drivers/iio/adc/Makefile
++++ b/drivers/iio/adc/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_MCP3911) += mcp3911.o
+ obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
+ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
+ obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
++obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o
+ obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
+ obj-$(CONFIG_NAU7802) += nau7802.o
+ obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
+diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c
+new file mode 100644
+index 0000000..962058e
+--- /dev/null
++++ b/drivers/iio/adc/rtq6056.c
+@@ -0,0 +1,649 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2022 Richtek Technology Corp.
++ *
++ * ChiYuan Huang <cy_huang@richtek.com>
++ */
++
++#include <linux/bitops.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/pm_runtime.h>
++#include <linux/property.h>
++#include <linux/regmap.h>
++#include <linux/sysfs.h>
++#include <linux/types.h>
++#include <linux/util_macros.h>
++
++#include <linux/iio/buffer.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/driver.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#define RTQ6056_REG_CONFIG	0x00
++#define RTQ6056_REG_SHUNTVOLT	0x01
++#define RTQ6056_REG_BUSVOLT	0x02
++#define RTQ6056_REG_POWER	0x03
++#define RTQ6056_REG_CURRENT	0x04
++#define RTQ6056_REG_CALIBRATION	0x05
++#define RTQ6056_REG_MASKENABLE	0x06
++#define RTQ6056_REG_ALERTLIMIT	0x07
++#define RTQ6056_REG_MANUFACTID	0xFE
++#define RTQ6056_REG_DIEID	0xFF
++
++#define RTQ6056_MAX_CHANNEL	4
++#define RTQ6056_VENDOR_ID	0x1214
++#define RTQ6056_DEFAULT_CONFIG	0x4127
++#define RTQ6056_CONT_ALLON	7
++
++#define RTQ6056_CONFIG_OPMODE_MASK	GENMASK(2, 0)
++#define RTQ6056_CONFIG_OPMODE(x)	((x << 0) & RTQ6056_CONFIG_OPMODE_MASK)
++#define RTQ6056_CONFIG_VSHUNTCT_MASK	GENMASK(5, 3)
++#define RTQ6056_CONFIG_VSHUNTCT(x)	((x << 3) & \
++					 RTQ6056_CONFIG_VSHUNTCT_MASK)
++#define RTQ6056_CONFIG_VBUSCT_MASK	GENMASK(8, 6)
++#define RTQ6056_CONFIG_VBUSCT(x)	((x << 6) & RTQ6056_CONFIG_VBUSCT_MASK)
++#define RTQ6056_CONFIG_AVG_MASK		GENMASK(11, 9)
++#define RTQ6056_CONFIG_AVG(x)		((x << 9) & RTQ6056_CONFIG_AVG_MASK)
++#define RTQ6056_CONFIG_RESET_MASK	GENMASK(15, 15)
++#define RTQ6056_CONFIG_RESET(x)		((x << 15) & RTQ6056_CONFIG_RESET_MASK)
++
++struct rtq6056_priv {
++	struct device *dev;
++	struct regmap *regmap;
++	u32 shunt_resistor_uohm;
++	int vshuntct_us;
++	int vbusct_us;
++	int avg_sample;
++};
++
++static struct iio_map rtq6056_maps[] = {
++	{
++		.consumer_dev_name = "voltage0",
++		.consumer_channel = "voltage0",
++		.adc_channel_label = "Vshunt",
++	}, {
++		.consumer_dev_name = "voltage1",
++		.consumer_channel = "voltage1",
++		.adc_channel_label = "Vbus",
++	}, {
++		.consumer_dev_name = "power2",
++		.consumer_channel = "power2",
++		.adc_channel_label = "Power",
++	}, {
++		.consumer_dev_name = "current3",
++		.consumer_channel = "current3",
++		.adc_channel_label = "Current",
++	}, { /* sentinel */ }
++};
++
++static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {
++	{
++		.type = IIO_VOLTAGE,
++		.indexed = 1,
++		.channel = 0,
++		.address = RTQ6056_REG_SHUNTVOLT,
++		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++				      BIT(IIO_CHAN_INFO_SCALE) |
++				      BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.scan_index = 0,
++		.scan_type = {
++			.sign = 's',
++			.realbits = 16,
++			.storagebits = 16,
++			.endianness = IIO_CPU,
++		},
++		.datasheet_name = "voltage0",
++	},
++	{
++		.type = IIO_VOLTAGE,
++		.indexed = 1,
++		.channel = 1,
++		.address = RTQ6056_REG_BUSVOLT,
++		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++				      BIT(IIO_CHAN_INFO_SCALE) |
++				      BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.scan_index = 1,
++		.scan_type = {
++			.sign = 'u',
++			.realbits = 16,
++			.storagebits = 16,
++			.endianness = IIO_CPU,
++		},
++		.datasheet_name = "voltage1",
++	},
++	{
++		.type = IIO_POWER,
++		.indexed = 1,
++		.channel = 2,
++		.address = RTQ6056_REG_POWER,
++		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++				      BIT(IIO_CHAN_INFO_SCALE) |
++				      BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.scan_index = 2,
++		.scan_type = {
++			.sign = 'u',
++			.realbits = 16,
++			.storagebits = 16,
++			.endianness = IIO_CPU,
++		},
++		.datasheet_name = "power2",
++	},
++	{
++		.type = IIO_CURRENT,
++		.indexed = 1,
++		.channel = 3,
++		.address = RTQ6056_REG_CURRENT,
++		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++				      BIT(IIO_CHAN_INFO_SAMP_FREQ),
++		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
++		.scan_index = 3,
++		.scan_type = {
++			.sign = 's',
++			.realbits = 16,
++			.storagebits = 16,
++			.endianness = IIO_CPU,
++		},
++		.datasheet_name = "current3",
++	},
++	IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
++};
++
++static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,
++				    struct iio_chan_spec const *ch,
++				    int *val)
++{
++	struct device *dev = priv->dev;
++	unsigned int addr = ch->address;
++	unsigned int regval;
++	int ret;
++
++	pm_runtime_get_sync(dev);
++	ret = regmap_read(priv->regmap, addr, &regval);
++	pm_runtime_mark_last_busy(dev);
++	pm_runtime_put(dev);
++	if (ret)
++		return ret;
++
++	/* Power and VBUS is unsigned 16-bit, others are signed 16-bit */
++	if (addr == RTQ6056_REG_BUSVOLT || addr == RTQ6056_REG_POWER)
++		*val = regval;
++	else
++		*val = sign_extend32(regval, 16);
++
++	return IIO_VAL_INT;
++}
++
++static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,
++				  int *val2)
++{
++	switch (ch->address) {
++	case RTQ6056_REG_SHUNTVOLT:
++		/* VSHUNT lsb  2.5uV */
++		*val = 2500;
++		*val2 = 1000000;
++		return IIO_VAL_FRACTIONAL;
++	case RTQ6056_REG_BUSVOLT:
++		/* VBUS lsb 1.25mV */
++		*val = 1250;
++		*val2 = 1000;
++		return IIO_VAL_FRACTIONAL;
++	case RTQ6056_REG_POWER:
++		/* Power lsb 25mW */
++		*val = 25;
++		return IIO_VAL_INT;
++	default:
++		return -EINVAL;
++	}
++}
++
++/*
++ * Sample frequency for channel VSHUNT and VBUS. The indices correspond
++ * with the bit value expected by the chip. And it can be found at
++ * https://www.richtek.com/assets/product_file/RTQ6056/DSQ6056-00.pdf
++ */
++static const int rtq6056_samp_freq_list[] = {
++	7194, 4926, 3717, 1904, 964, 485, 243, 122,
++};
++
++static int rtq6056_adc_set_samp_freq(struct rtq6056_priv *priv,
++				     struct iio_chan_spec const *ch, int val)
++{
++	unsigned int selector;
++	int *ct, ret;
++
++	if (val > 7194 || val < 122)
++		return -EINVAL;
++
++	if (ch->address == RTQ6056_REG_SHUNTVOLT) {
++		ct = &priv->vshuntct_us;
++	} else if (ch->address == RTQ6056_REG_BUSVOLT) {
++		ct = &priv->vbusct_us;
++	} else
++		return -EINVAL;
++
++	selector = find_closest_descending(val, rtq6056_samp_freq_list,
++					   ARRAY_SIZE(rtq6056_samp_freq_list));
++
++	if (ch->address == RTQ6056_REG_SHUNTVOLT) {
++		ret = regmap_update_bits(priv->regmap, RTQ6056_REG_CONFIG,
++					 RTQ6056_CONFIG_VSHUNTCT_MASK,
++					 RTQ6056_CONFIG_VSHUNTCT(selector));
++	} else {
++		ret = regmap_update_bits(priv->regmap, RTQ6056_REG_CONFIG,
++					 RTQ6056_CONFIG_VBUSCT_MASK,
++					 RTQ6056_CONFIG_VBUSCT(selector));
++	}
++	if (ret)
++		return ret;
++
++	*ct = 1000000 / rtq6056_samp_freq_list[selector];
++
++	return 0;
++}
++
++/*
++ * Available averaging rate for rtq6056. The indices correspond with the bit
++ * value expected by the chip. And it can be found at
++ * https://www.richtek.com/assets/product_file/RTQ6056/DSQ6056-00.pdf
++ */
++static const int rtq6056_avg_sample_list[] = {
++	1, 4, 16, 64, 128, 256, 512, 1024,
++};
++
++static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)
++{
++	unsigned int selector;
++	int ret;
++
++	if (val > 1024 || val < 1)
++		return -EINVAL;
++
++	selector = find_closest(val, rtq6056_avg_sample_list,
++				ARRAY_SIZE(rtq6056_avg_sample_list));
++
++	ret = regmap_update_bits(priv->regmap, RTQ6056_REG_CONFIG,
++				 RTQ6056_CONFIG_AVG_MASK,
++				 RTQ6056_CONFIG_AVG(selector));
++
++	if (ret)
++		return ret;
++
++	priv->avg_sample = rtq6056_avg_sample_list[selector];
++
++	return 0;
++}
++
++static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv,
++				       struct iio_chan_spec const *ch, int *val)
++{
++	int sample_time;
++
++	if (ch->address == RTQ6056_REG_SHUNTVOLT)
++		sample_time = priv->vshuntct_us;
++	else if (ch->address == RTQ6056_REG_BUSVOLT)
++		sample_time = priv->vbusct_us;
++	else {
++		sample_time = priv->vshuntct_us + priv->vbusct_us;
++		sample_time *= priv->avg_sample;
++	}
++
++	*val = 1000000 / sample_time;
++
++	return IIO_VAL_INT;
++}
++
++static int rtq6056_adc_read_raw(struct iio_dev *indio_dev,
++				struct iio_chan_spec const *chan, int *val,
++				int *val2, long mask)
++{
++	struct rtq6056_priv *priv = iio_priv(indio_dev);
++
++	switch (mask) {
++	case IIO_CHAN_INFO_RAW:
++		return rtq6056_adc_read_channel(priv, chan, val);
++	case IIO_CHAN_INFO_SCALE:
++		return rtq6056_adc_read_scale(chan, val, val2);
++	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++		*val = priv->avg_sample;
++		return IIO_VAL_INT;
++	case IIO_CHAN_INFO_SAMP_FREQ:
++		return rtq6056_adc_get_sample_freq(priv, chan, val);
++	default:
++		return -EINVAL;
++	}
++}
++
++static int rtq6056_adc_read_avail(struct iio_dev *indio_dev,
++				  struct iio_chan_spec const *chan,
++				  const int **vals, int *type, int *length,
++				  long mask)
++{
++	switch (mask) {
++	case IIO_CHAN_INFO_SAMP_FREQ:
++		*vals = rtq6056_samp_freq_list;
++		*type = IIO_VAL_INT;
++		*length = ARRAY_SIZE(rtq6056_samp_freq_list);
++		return IIO_AVAIL_LIST;
++	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++		*vals = rtq6056_avg_sample_list;
++		*type = IIO_VAL_INT;
++		*length = ARRAY_SIZE(rtq6056_avg_sample_list);
++		return IIO_AVAIL_LIST;
++	default:
++		return -EINVAL;
++	}
++}
++
++static int rtq6056_adc_write_raw(struct iio_dev *indio_dev,
++				 struct iio_chan_spec const *chan, int val,
++				 int val2, long mask)
++{
++	struct rtq6056_priv *priv = iio_priv(indio_dev);
++	int ret;
++
++	ret = iio_device_claim_direct_mode(indio_dev);
++	if (ret)
++		return ret;
++
++	switch (mask) {
++	case IIO_CHAN_INFO_SAMP_FREQ:
++		ret = rtq6056_adc_set_samp_freq(priv, chan, val);
++		break;
++	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++		ret = rtq6056_adc_set_average(priv, val);
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	iio_device_release_direct_mode(indio_dev);
++
++	return ret;
++}
++
++static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,
++				      int resistor_uohm)
++{
++	unsigned int calib_val;
++	int ret;
++
++	if (resistor_uohm <= 0) {
++		dev_err(priv->dev, "Invalid resistor [%d]\n", resistor_uohm);
++		return -EINVAL;
++	}
++
++	/* calibration = 5120000 / (Rshunt (uOhm) * current lsb (1mA)) */
++	calib_val = 5120000 / resistor_uohm;
++	ret = regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val);
++	if (ret)
++		return ret;
++
++	priv->shunt_resistor_uohm = resistor_uohm;
++
++	return 0;
++}
++
++static ssize_t shunt_resistor_show(struct device *dev,
++				   struct device_attribute *attr, char *buf)
++{
++	struct rtq6056_priv *priv = iio_priv(dev_to_iio_dev(dev));
++	int vals[2] = { priv->shunt_resistor_uohm, 1000000 };
++
++	return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals);
++}
++
++static ssize_t shunt_resistor_store(struct device *dev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t len)
++{
++	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++	struct rtq6056_priv *priv = iio_priv(indio_dev);
++	int val, val_fract, ret;
++
++	ret = iio_device_claim_direct_mode(indio_dev);
++	if (ret)
++		return ret;
++
++	ret = iio_str_to_fixpoint(buf, 100000, &val, &val_fract);
++	if (ret)
++		goto out_store;
++
++	ret = rtq6056_set_shunt_resistor(priv, val * 1000000 + val_fract);
++
++out_store:
++	iio_device_release_direct_mode(indio_dev);
++
++	return ret ?: len;
++}
++
++static IIO_DEVICE_ATTR_RW(shunt_resistor, 0);
++
++static struct attribute *rtq6056_attributes[] = {
++	&iio_dev_attr_shunt_resistor.dev_attr.attr,
++	NULL
++};
++
++static const struct attribute_group rtq6056_attribute_group = {
++	.attrs = rtq6056_attributes,
++};
++
++static const struct iio_info rtq6056_info = {
++	.attrs = &rtq6056_attribute_group,
++	.read_raw = rtq6056_adc_read_raw,
++	.read_avail = rtq6056_adc_read_avail,
++	.write_raw = rtq6056_adc_write_raw,
++};
++
++static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p)
++{
++	struct iio_poll_func *pf = p;
++	struct iio_dev *indio_dev = pf->indio_dev;
++	struct rtq6056_priv *priv = iio_priv(indio_dev);
++	struct device *dev = priv->dev;
++	struct {
++		u16 vals[RTQ6056_MAX_CHANNEL];
++		s64 timestamp __aligned(8);
++	} data;
++	unsigned int raw;
++	int i = 0, bit, ret;
++
++	memset(&data, 0, sizeof(data));
++
++	pm_runtime_get_sync(dev);
++
++	for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) {
++		unsigned int addr = rtq6056_channels[bit].address;
++
++		ret = regmap_read(priv->regmap, addr, &raw);
++		if (ret)
++			goto out;
++
++		data.vals[i++] = raw;
++	}
++
++	iio_push_to_buffers_with_timestamp(indio_dev, &data, iio_get_time_ns(indio_dev));
++
++out:
++	pm_runtime_mark_last_busy(dev);
++	pm_runtime_put(dev);
++
++	iio_trigger_notify_done(indio_dev->trig);
++
++	return IRQ_HANDLED;
++}
++
++static void rtq6056_enter_shutdown_state(void *dev)
++{
++	struct rtq6056_priv *priv = dev_get_drvdata(dev);
++
++	/* Enter shutdown state */
++	regmap_update_bits(priv->regmap, RTQ6056_REG_CONFIG,
++			   RTQ6056_CONFIG_OPMODE_MASK,
++			   RTQ6056_CONFIG_OPMODE(0));
++}
++
++static bool rtq6056_is_readable_reg(struct device *dev, unsigned int reg)
++{
++	switch (reg) {
++	case RTQ6056_REG_CONFIG ... RTQ6056_REG_ALERTLIMIT:
++	case RTQ6056_REG_MANUFACTID ... RTQ6056_REG_DIEID:
++		return true;
++	default:
++		return false;
++	}
++}
++
++static bool rtq6056_is_writeable_reg(struct device *dev, unsigned int reg)
++{
++	switch (reg) {
++	case RTQ6056_REG_CONFIG:
++	case RTQ6056_REG_CALIBRATION ... RTQ6056_REG_ALERTLIMIT:
++		return true;
++	default:
++		return false;
++	}
++}
++
++static const struct regmap_config rtq6056_regmap_config = {
++	.reg_bits = 8,
++	.val_bits = 16,
++	.val_format_endian = REGMAP_ENDIAN_BIG,
++	.max_register = RTQ6056_REG_DIEID,
++	.readable_reg = rtq6056_is_readable_reg,
++	.writeable_reg = rtq6056_is_writeable_reg,
++};
++
++static int rtq6056_probe(struct i2c_client *i2c)
++{
++	struct iio_dev *indio_dev;
++	struct rtq6056_priv *priv;
++	struct device *dev = &i2c->dev;
++	struct regmap *regmap;
++	unsigned int vendor_id, shunt_resistor_uohm;
++	int ret;
++
++	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA))
++		return -EOPNOTSUPP;
++
++	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
++	if (!indio_dev)
++		return -ENOMEM;
++
++	priv = iio_priv(indio_dev);
++	priv->dev = dev;
++	priv->vshuntct_us = priv->vbusct_us = 1037;
++	priv->avg_sample = 1;
++	i2c_set_clientdata(i2c, priv);
++
++	regmap = devm_regmap_init_i2c(i2c, &rtq6056_regmap_config);
++	if (IS_ERR(regmap)) {
++		dev_err(dev, "Failed to init regmap\n");
++		return PTR_ERR(regmap);
++	}
++
++	priv->regmap = regmap;
++
++	ret = regmap_read(regmap, RTQ6056_REG_MANUFACTID, &vendor_id);
++	if (ret) {
++		dev_err(dev, "Failed to get manufacturer info: %d\n", ret);
++		return ret;
++	}
++
++	if (vendor_id != RTQ6056_VENDOR_ID) {
++		dev_err(dev, "Invalid vendor id 0x%04x\n", vendor_id);
++		return -ENODEV;
++	}
++
++	/*
++	 * By default, configure average sample as 1, bus and shunt conversion
++	 * time as 1037 microsecond, and operating mode to all on.
++	 */
++	ret = regmap_write(regmap, RTQ6056_REG_CONFIG, RTQ6056_DEFAULT_CONFIG);
++	if (ret) {
++		dev_err(dev, "Failed to enable continuous sensing: %d\n", ret);
++		return ret;
++	}
++
++	ret = devm_add_action_or_reset(dev, rtq6056_enter_shutdown_state, dev);
++	if (ret)
++		return ret;
++
++	/* By default, use 2000 micro-Ohm resistor */
++	shunt_resistor_uohm = 2000;
++	device_property_read_u32(dev, "shunt-resistor-micro-ohms",
++				 &shunt_resistor_uohm);
++
++	ret = rtq6056_set_shunt_resistor(priv, shunt_resistor_uohm);
++	if (ret) {
++		dev_err(dev, "Failed to init shunt resistor: %d\n", ret);
++		goto err;
++	}
++
++	indio_dev->name = "rtq6056";
++	indio_dev->modes = INDIO_DIRECT_MODE;
++	indio_dev->channels = rtq6056_channels;
++	indio_dev->num_channels = ARRAY_SIZE(rtq6056_channels);
++	indio_dev->info = &rtq6056_info;
++
++	ret = iio_map_array_register(indio_dev, rtq6056_maps);
++	if (ret) {
++		dev_err(dev, "Failed to register iio map: %d\n", ret);
++		goto err;
++	}
++
++	ret = iio_triggered_buffer_setup(indio_dev, NULL,
++					 &rtq6056_buffer_trigger_handler, NULL);
++
++	if (ret) {
++		dev_err(dev, "Failed to allocate iio trigger buffer: %d\n",
++			ret);
++		goto err;
++	}
++
++	ret = devm_iio_device_register(dev, indio_dev);
++	if (ret) {
++		dev_err(dev, "Failed to register iio device: %d\n", ret);
++		goto err;
++	}
++
++	return 0;
++
++err:
++	return ret;
++}
++
++static const struct of_device_id rtq6056_device_match[] = {
++	{ .compatible = "richtek,rtq6056" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, rtq6056_device_match);
++
++static struct i2c_driver rtq6056_driver = {
++	.driver = {
++		.name = "rtq6056",
++		.of_match_table = rtq6056_device_match,
++	},
++	.probe_new = rtq6056_probe,
++};
++module_i2c_driver(rtq6056_driver);
++
++MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
++MODULE_DESCRIPTION("Richtek RTQ6056 Driver");
++MODULE_LICENSE("GPL v2");
+-- 
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/408-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/408-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
index e4e283c..f9c3542 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/408-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
@@ -1,3 +1,22 @@
+From 0aeb63ff705a42b9140cad179ebe7f5fc54d285c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:09 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch]
+
+---
+ drivers/mtd/nand/spi/core.c       | 86 ++++++++++++++++++++++---------
+ drivers/mtd/nand/spi/gigadevice.c | 45 +++++-----------
+ drivers/mtd/nand/spi/macronix.c   | 30 +++--------
+ drivers/mtd/nand/spi/micron.c     | 26 ++--------
+ drivers/mtd/nand/spi/paragon.c    | 28 +++-------
+ drivers/mtd/nand/spi/toshiba.c    | 42 +++++----------
+ drivers/mtd/nand/spi/winbond.c    | 34 +++---------
+ include/linux/mtd/spinand.h       | 66 ++++++++++++++++--------
+ 8 files changed, 155 insertions(+), 202 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
+index 55e636efc..9f5f95ff7 100644
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
 @@ -16,6 +16,7 @@
@@ -23,7 +42,7 @@
  	int ret;
  
  	ret = spi_mem_exec_op(spinand->spimem, &op);
-@@ -760,24 +762,62 @@ static const struct spinand_manufacturer
+@@ -760,24 +762,62 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = {
  	&winbond_spinand_manufacturer,
  };
  
@@ -95,7 +114,7 @@
  static int spinand_manufacturer_init(struct spinand_device *spinand)
  {
  	if (spinand->manufacturer->ops->init)
-@@ -833,9 +873,9 @@ spinand_select_op_variant(struct spinand
+@@ -833,9 +873,9 @@ spinand_select_op_variant(struct spinand_device *spinand,
   * @spinand: SPI NAND object
   * @table: SPI NAND device description table
   * @table_size: size of the device description table
@@ -107,7 +126,7 @@
   * entry in the SPI NAND description table. If a match is found, the spinand
   * object will be initialized with information provided by the matching
   * spinand_info entry.
-@@ -844,8 +884,10 @@ spinand_select_op_variant(struct spinand
+@@ -844,8 +884,10 @@ spinand_select_op_variant(struct spinand_device *spinand,
   */
  int spinand_match_and_init(struct spinand_device *spinand,
  			   const struct spinand_info *table,
@@ -119,7 +138,7 @@
  	struct nand_device *nand = spinand_to_nand(spinand);
  	unsigned int i;
  
-@@ -853,13 +895,17 @@ int spinand_match_and_init(struct spinan
+@@ -853,13 +895,17 @@ int spinand_match_and_init(struct spinand_device *spinand,
  		const struct spinand_info *info = &table[i];
  		const struct spi_mem_op *op;
  
@@ -138,7 +157,7 @@
  		spinand->select_target = table[i].select_target;
  
  		op = spinand_select_op_variant(spinand,
-@@ -896,13 +942,7 @@ static int spinand_detect(struct spinand
+@@ -896,13 +942,7 @@ static int spinand_detect(struct spinand_device *spinand)
  	if (ret)
  		return ret;
  
@@ -153,9 +172,11 @@
  	if (ret) {
  		dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
  			spinand->id.data);
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index b13b39763..a34c5ede1 100644
 --- a/drivers/mtd/nand/spi/gigadevice.c
 +++ b/drivers/mtd/nand/spi/gigadevice.c
-@@ -195,7 +195,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(
+@@ -195,7 +195,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
  }
  
  static const struct spinand_info gigadevice_spinand_table[] = {
@@ -165,7 +186,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -204,7 +205,8 @@ static const struct spinand_info gigadev
+@@ -204,7 +205,8 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
  				     gd5fxgq4xa_ecc_get_status)),
@@ -175,7 +196,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -213,7 +215,8 @@ static const struct spinand_info gigadev
+@@ -213,7 +215,8 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
  				     gd5fxgq4xa_ecc_get_status)),
@@ -185,7 +206,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -222,7 +225,8 @@ static const struct spinand_info gigadev
+@@ -222,7 +225,8 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
  				     gd5fxgq4xa_ecc_get_status)),
@@ -195,7 +216,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -231,7 +235,8 @@ static const struct spinand_info gigadev
+@@ -231,7 +235,8 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
  				     gd5fxgq4uexxg_ecc_get_status)),
@@ -205,7 +226,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
-@@ -242,39 +247,13 @@ static const struct spinand_info gigadev
+@@ -242,39 +247,13 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  				     gd5fxgq4ufxxg_ecc_get_status)),
  };
  
@@ -247,9 +268,11 @@
 +	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
  	.ops = &gigadevice_spinand_manuf_ops,
  };
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index 21def3f8f..0f900f3aa 100644
 --- a/drivers/mtd/nand/spi/macronix.c
 +++ b/drivers/mtd/nand/spi/macronix.c
-@@ -99,7 +99,8 @@ static int mx35lf1ge4ab_ecc_get_status(s
+@@ -99,7 +99,8 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
  }
  
  static const struct spinand_info macronix_spinand_table[] = {
@@ -259,7 +282,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(4, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -108,7 +109,8 @@ static const struct spinand_info macroni
+@@ -108,7 +109,8 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
@@ -269,7 +292,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
  		     NAND_ECCREQ(4, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -118,33 +120,13 @@ static const struct spinand_info macroni
+@@ -118,33 +120,13 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
  };
  
@@ -305,9 +328,11 @@
 +	.nchips = ARRAY_SIZE(macronix_spinand_table),
  	.ops = &macronix_spinand_manuf_ops,
  };
+diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
+index 7d7b1f7fc..f56f81325 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
-@@ -91,7 +91,8 @@ static int mt29f2g01abagd_ecc_get_status
+@@ -91,7 +91,8 @@ static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand,
  }
  
  static const struct spinand_info micron_spinand_table[] = {
@@ -317,7 +342,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -102,32 +103,13 @@ static const struct spinand_info micron_
+@@ -102,32 +103,13 @@ static const struct spinand_info micron_spinand_table[] = {
  				     mt29f2g01abagd_ecc_get_status)),
  };
  
@@ -352,9 +377,11 @@
 +	.nchips = ARRAY_SIZE(micron_spinand_table),
  	.ops = &micron_spinand_manuf_ops,
  };
+diff --git a/drivers/mtd/nand/spi/paragon.c b/drivers/mtd/nand/spi/paragon.c
+index 52307681c..519ade513 100644
 --- a/drivers/mtd/nand/spi/paragon.c
 +++ b/drivers/mtd/nand/spi/paragon.c
-@@ -97,7 +97,8 @@ static const struct mtd_ooblayout_ops pn
+@@ -97,7 +97,8 @@ static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
  
  
  static const struct spinand_info paragon_spinand_table[] = {
@@ -364,7 +391,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -106,7 +107,8 @@ static const struct spinand_info paragon
+@@ -106,7 +107,8 @@ static const struct spinand_info paragon_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
  				     pn26g0xa_ecc_get_status)),
@@ -374,7 +401,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -117,31 +119,13 @@ static const struct spinand_info paragon
+@@ -117,31 +119,13 @@ static const struct spinand_info paragon_spinand_table[] = {
  				     pn26g0xa_ecc_get_status)),
  };
  
@@ -408,9 +435,11 @@
 +	.nchips = ARRAY_SIZE(paragon_spinand_table),
  	.ops = &paragon_spinand_manuf_ops,
  };
+diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
+index 1cb3760ff..35da3c6e9 100644
 --- a/drivers/mtd/nand/spi/toshiba.c
 +++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -95,7 +95,8 @@ static int tc58cxgxsx_ecc_get_status(str
+@@ -95,7 +95,8 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
  
  static const struct spinand_info toshiba_spinand_table[] = {
  	/* 3.3V 1Gb */
@@ -420,7 +449,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -105,7 +106,8 @@ static const struct spinand_info toshiba
+@@ -105,7 +106,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
  				     tc58cxgxsx_ecc_get_status)),
  	/* 3.3V 2Gb */
@@ -430,7 +459,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -115,7 +117,8 @@ static const struct spinand_info toshiba
+@@ -115,7 +117,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
  				     tc58cxgxsx_ecc_get_status)),
  	/* 3.3V 4Gb */
@@ -440,7 +469,7 @@
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -125,7 +128,8 @@ static const struct spinand_info toshiba
+@@ -125,7 +128,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
  				     tc58cxgxsx_ecc_get_status)),
  	/* 1.8V 1Gb */
@@ -450,7 +479,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -135,7 +139,8 @@ static const struct spinand_info toshiba
+@@ -135,7 +139,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
  				     tc58cxgxsx_ecc_get_status)),
  	/* 1.8V 2Gb */
@@ -460,7 +489,7 @@
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -145,7 +150,8 @@ static const struct spinand_info toshiba
+@@ -145,7 +150,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
  				     tc58cxgxsx_ecc_get_status)),
  	/* 1.8V 4Gb */
@@ -470,7 +499,7 @@
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -156,33 +162,13 @@ static const struct spinand_info toshiba
+@@ -156,33 +162,13 @@ static const struct spinand_info toshiba_spinand_table[] = {
  				     tc58cxgxsx_ecc_get_status)),
  };
  
@@ -506,9 +535,11 @@
 +	.nchips = ARRAY_SIZE(toshiba_spinand_table),
  	.ops = &toshiba_spinand_manuf_ops,
  };
+diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
+index a6c17e0ca..766844283 100644
 --- a/drivers/mtd/nand/spi/winbond.c
 +++ b/drivers/mtd/nand/spi/winbond.c
-@@ -75,7 +75,8 @@ static int w25m02gv_select_target(struct
+@@ -75,7 +75,8 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
  }
  
  static const struct spinand_info winbond_spinand_table[] = {
@@ -518,7 +549,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -84,7 +85,8 @@ static const struct spinand_info winbond
+@@ -84,7 +85,8 @@ static const struct spinand_info winbond_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
  		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
@@ -528,7 +559,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -94,31 +96,6 @@ static const struct spinand_info winbond
+@@ -94,31 +96,6 @@ static const struct spinand_info winbond_spinand_table[] = {
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
  };
  
@@ -560,7 +591,7 @@
  static int winbond_spinand_init(struct spinand_device *spinand)
  {
  	struct nand_device *nand = spinand_to_nand(spinand);
-@@ -138,12 +115,13 @@ static int winbond_spinand_init(struct s
+@@ -138,12 +115,13 @@ static int winbond_spinand_init(struct spinand_device *spinand)
  }
  
  static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
@@ -575,6 +606,8 @@
 +	.nchips = ARRAY_SIZE(winbond_spinand_table),
  	.ops = &winbond_spinand_manuf_ops,
  };
+diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
+index 4ea558bd3..f4c4ae871 100644
 --- a/include/linux/mtd/spinand.h
 +++ b/include/linux/mtd/spinand.h
 @@ -32,9 +32,9 @@
@@ -693,7 +726,7 @@
  #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update)		\
  	{								\
  		.read_cache = __read,					\
-@@ -451,9 +472,10 @@ static inline void spinand_set_of_node(s
+@@ -451,9 +472,10 @@ static inline void spinand_set_of_node(struct spinand_device *spinand,
  	nanddev_set_of_node(&spinand->base, np);
  }
  
@@ -706,3 +739,6 @@
  
  int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
  int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/411-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch
similarity index 66%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/411-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch
index d4e9497..e3e81e5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/411-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch
@@ -1,48 +1,15 @@
-From 469b992489852b500d39048aa0013639dfe9f2e6 Mon Sep 17 00:00:00 2001
-From: Reto Schneider <reto.schneider@husqvarnagroup.com>
-Date: Thu, 11 Feb 2021 12:36:19 +0100
-Subject: [PATCH] mtd: spinand: gigadevice: Support GD5F1GQ5UExxG
+From 2f8ed664925318dacb6a92ca6383b5589cc2f7e1 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:09 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch]
 
-The relevant changes to the already existing GD5F1GQ4UExxG support has
-been determined by consulting the GigaDevice product change notice
-AN-0392-10, version 1.0 from November 30, 2020.
-
-As the overlaps are huge, variable names have been generalized
-accordingly.
-
-Apart from the lowered ECC strength (4 instead of 8 bits per 512 bytes),
-the new device ID, and the extra quad IO dummy byte, no changes had to
-be taken into account.
-
-New hardware features are not supported, namely:
- - Power on reset
- - Unique ID
- - Double transfer rate (DTR)
- - Parameter page
- - Random data quad IO
-
-The inverted semantic of the "driver strength" register bits, defaulting
-to 100% instead of 50% for the Q5 devices, got ignored as the driver has
-never touched them anyway.
-
-The no longer supported "read from cache during block erase"
-functionality is not reflected as the current SPI NAND core does not
-support it anyway.
-
-Implementation has been tested on MediaTek MT7688 based GARDENA smart
-Gateways using both, GigaDevice GD5F1GQ5UEYIG and GD5F1GQ4UBYIG.
-
-Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
-Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
-Reviewed-by: Stefan Roese <sr@denx.de>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20210211113619.3502-1-code@reto-schneider.ch
 ---
  drivers/mtd/nand/spi/gigadevice.c | 69 +++++++++++++++++++++++++++----
  1 file changed, 60 insertions(+), 9 deletions(-)
 
 diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
-index 33c67403c4aa1e..1dd1c589809341 100644
+index a34c5ede1..937a04ce6 100644
 --- a/drivers/mtd/nand/spi/gigadevice.c
 +++ b/drivers/mtd/nand/spi/gigadevice.c
 @@ -13,7 +13,10 @@
@@ -75,7 +42,7 @@
  					struct mtd_oob_region *region)
  {
  	if (section)
-@@ -127,9 +130,10 @@ static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
+@@ -127,16 +130,17 @@ static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
  	return 0;
  }
  
@@ -88,8 +55,7 @@
 +	.free = gd5fxgqx_variant2_ooblayout_free,
  };
  
- static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
-@@ -165,7 +169,7 @@ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
  					u8 status)
  {
  	u8 status2;
@@ -98,7 +64,7 @@
  						      &status2);
  	int ret;
  
-@@ -203,6 +207,43 @@ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+@@ -174,6 +178,43 @@ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
  	return -EINVAL;
  }
  
@@ -142,7 +108,7 @@
  static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
  					u8 status)
  {
-@@ -282,7 +323,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
+@@ -233,7 +274,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
@@ -151,7 +117,7 @@
  				     gd5fxgq4uexxg_ecc_get_status)),
  	SPINAND_INFO("GD5F1GQ4UFxxG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
-@@ -292,8 +333,18 @@ static const struct spinand_info gigadevice_spinand_table[] = {
+@@ -243,8 +284,18 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
@@ -171,3 +137,6 @@
  };
  
  static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
new file mode 100644
index 0000000..d55e946
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
@@ -0,0 +1,34 @@
+From 9c8aa0697168dac0ad3638dc075c25087d4ee19c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:10 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch]
+
+---
+ drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index 0f900f3aa..6e66d8710 100644
+--- a/drivers/mtd/nand/spi/macronix.c
++++ b/drivers/mtd/nand/spi/macronix.c
+@@ -118,6 +118,16 @@ static const struct spinand_info macronix_spinand_table[] = {
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++	SPINAND_INFO("MX31LF1GE4BC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0 /*SPINAND_HAS_QE_BIT*/,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
+ };
+ 
+ static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
new file mode 100644
index 0000000..8dcf798
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
@@ -0,0 +1,34 @@
+From 34485df92908238e8603d2c9de486e7c41db45fb Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:10 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch]
+
+---
+ drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index 6e66d8710..4964fe35b 100644
+--- a/drivers/mtd/nand/spi/macronix.c
++++ b/drivers/mtd/nand/spi/macronix.c
+@@ -128,6 +128,16 @@ static const struct spinand_info macronix_spinand_table[] = {
+ 		     0 /*SPINAND_HAS_QE_BIT*/,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ 				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX31UF1GE4BC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0 /*SPINAND_HAS_QE_BIT*/,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
+ };
+ 
+ static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/432-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
similarity index 63%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/432-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
index 313b373..eaa9851 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/432-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
@@ -1,27 +1,18 @@
-From 5ece78de88739b4c68263e9f2582380c1fd8314f Mon Sep 17 00:00:00 2001
-From: YouChing Lin <ycllin@mxic.com.tw>
-Date: Thu, 5 Nov 2020 15:23:40 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add support for MX35LFxGE4AD
+From 14f6824f11e1167bf2cbbd650cd6a7a2ad856555 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:10 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch]
 
-The Macronix MX35LF2GE4AD / MX35LF4GE4AD are 3V, 2G / 4Gbit serial
-SLC NAND flash device (with on-die ECC).
-
-Validated by read, erase, read back, write, read back and nandtest
-on Xilinx Zynq PicoZed FPGA board which included Macronix SPI Host
-(drivers/spi/spi-mxic.c).
-
-Signed-off-by: YouChing Lin <ycllin@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1604561020-13499-1-git-send-email-ycllin@mxic.com.tw
 ---
  drivers/mtd/nand/spi/macronix.c | 20 ++++++++++++++++++++
  1 file changed, 20 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 8e801e4c3a006f..3786b1b03b3b4b 100644
+index 4964fe35b..16d2acafb 100644
 --- a/drivers/mtd/nand/spi/macronix.c
 +++ b/drivers/mtd/nand/spi/macronix.c
-@@ -119,6 +119,26 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -118,6 +118,26 @@ static const struct spinand_info macronix_spinand_table[] = {
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
@@ -48,3 +39,6 @@
  	SPINAND_INFO("MX31LF1GE4BC",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/433-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
similarity index 64%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/433-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
index e323a53..41b540c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/433-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
@@ -1,28 +1,18 @@
-From ee4e0eafa43cfd9008722fe15e17b8bf62fb6e8d Mon Sep 17 00:00:00 2001
-From: YouChing Lin <ycllin@mxic.com.tw>
-Date: Thu, 10 Dec 2020 11:22:09 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add support for MX35LFxG24AD
+From 1de538322f8e3b2586d5b41bdcc0383ecba9ce32 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:10 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch]
 
-The Macronix MX35LF1G24AD(/2G24AD/4G24AD) are 3V, 1G/2G/4Gbit serial
-SLC NAND flash device (without on-die ECC).
-
-Validated by read, erase, read back, write, read back on Xilinx Zynq
-PicoZed FPGA board which included Macronix SPI Host(drivers/spi/spi-mxic.c)
-& S/W BCH ecc(drivers/mtd/nand/ecc-sw-bch.c) with bug fixing patch
-(mtd: nand: ecc-bch: Fix the size of calc_buf/code_buf of the BCH).
-
-Signed-off-by: YouChing Lin <ycllin@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1607570529-22341-3-git-send-email-ycllin@mxic.com.tw
 ---
  drivers/mtd/nand/spi/macronix.c | 27 +++++++++++++++++++++++++++
  1 file changed, 27 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 3786b1b03b3b4b..6701aaa21a49df 100644
+index 16d2acafb..e0c71c654 100644
 --- a/drivers/mtd/nand/spi/macronix.c
 +++ b/drivers/mtd/nand/spi/macronix.c
-@@ -139,6 +139,33 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -138,6 +138,33 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
@@ -56,3 +46,6 @@
  	SPINAND_INFO("MX31LF1GE4BC",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/434-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
similarity index 72%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/434-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
index 9900084..fbcca17 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/434-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
@@ -1,55 +1,18 @@
-From c374839f9b4475173e536d1eaddff45cb481dbdf Mon Sep 17 00:00:00 2001
-From: Jaime Liao <jaimeliao@mxic.com.tw>
-Date: Thu, 20 May 2021 09:45:08 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add support for serial NAND flash
+From 3b7dc97f2ff2d354c7f624d4d04fd5dd8595c923 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:11 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch]
 
-Macronix NAND Flash devices are available in different configurations
-and densities.
-
-MX"35" means SPI NAND
-MX35"LF"/"UF" , LF means 3V and UF meands 1.8V
-MX35LF"2G" , 2G means 2Gbits
-MX35LF2G"E4"/"24"/"14",
-E4 means internal ECC and Quad I/O(x4)
-24 means 8-bit ecc requirement and Quad I/O(x4)
-14 means 4-bit ecc requirement and Quad I/O(x4)
-
-MX35LF2G14AC is 3V 2Gbit serial NAND flash device
-(without on-die ECC)
-https://www.mxic.com.tw/Lists/Datasheet/Attachments/7926/MX35LF2G14AC,%203V,%202Gb,%20v1.1.pdf
-
-MX35UF4G24AD is 1.8V 4Gbit serial NAND flash device
-(without on-die ECC)
-https://www.mxic.com.tw/Lists/Datasheet/Attachments/7980/MX35UF4G24AD,%201.8V,%204Gb,%20v0.00.pdf
-
-MX35UF4GE4AD/MX35UF2GE4AD are 1.8V 4G/2Gbit serial
-NAND flash device with 8-bit on-die ECC
-https://www.mxic.com.tw/Lists/Datasheet/Attachments/7983/MX35UF4GE4AD,%201.8V,%204Gb,%20v0.00.pdf
-
-MX35UF2GE4AC/MX35UF1GE4AC are 1.8V 2G/1Gbit serial
-NAND flash device with 8-bit on-die ECC
-https://www.mxic.com.tw/Lists/Datasheet/Attachments/7974/MX35UF2GE4AC,%201.8V,%202Gb,%20v1.0.pdf
-
-MX35UF2G14AC/MX35UF1G14AC are 1.8V 2G/1Gbit serial
-NAND flash device (without on-die ECC)
-https://www.mxic.com.tw/Lists/Datasheet/Attachments/7931/MX35UF2G14AC,%201.8V,%202Gb,%20v1.1.pdf
-
-Validated via normal(default) and QUAD mode by read, erase, read back,
-on Xilinx Zynq PicoZed FPGA board which included Macronix
-SPI Host(drivers/spi/spi-mxic.c).
-
-Signed-off-by: Jaime Liao <jaimeliao@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1621475108-22523-1-git-send-email-jaimeliao@mxic.com.tw
 ---
  drivers/mtd/nand/spi/macronix.c | 112 ++++++++++++++++++++++++++++++++
  1 file changed, 112 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 6701aaa21a49df..a9890350db0293 100644
+index e0c71c654..ede66b71b 100644
 --- a/drivers/mtd/nand/spi/macronix.c
 +++ b/drivers/mtd/nand/spi/macronix.c
-@@ -186,6 +186,118 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -185,6 +185,118 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     0 /*SPINAND_HAS_QE_BIT*/,
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
@@ -168,3 +131,6 @@
  };
  
  static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/435-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/435-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
index cc6900a..bcc9df8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/435-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
@@ -1,27 +1,18 @@
-From 6f802696c2faf0119781fc3b7977a4eedf9ab239 Mon Sep 17 00:00:00 2001
-From: Jaime Liao <jaimeliao@mxic.com.tw>
-Date: Mon, 9 Aug 2021 09:27:52 +0800
-Subject: [PATCH] mtd: spinand: macronix: Add Quad support for serial NAND
- flash
+From ec328d836a28d538c38f67f5467b9319d6a950a3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:11 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch]
 
-Adding FLAG "SPINAND_HAS_QE_BIT" for Quad mode support on Macronix
-Serial Flash.
-Validated via normal(default) and QUAD mode by read, erase, read back,
-on Xilinx Zynq PicoZed FPGA board which included Macronix
-SPI Host(drivers/spi/spi-mxic.c).
-
-Signed-off-by: Jaime Liao <jaimeliao@mxic.com.tw>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/1628472472-32008-1-git-send-email-jaimeliao@mxic.com.tw
 ---
  drivers/mtd/nand/spi/macronix.c | 16 ++++++++--------
  1 file changed, 8 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index a9890350db0293..3f31f1381a62c0 100644
+index ede66b71b..25319b4f8 100644
 --- a/drivers/mtd/nand/spi/macronix.c
 +++ b/drivers/mtd/nand/spi/macronix.c
-@@ -126,7 +126,7 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -125,7 +125,7 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -30,7 +21,7 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
  	SPINAND_INFO("MX35LF4GE4AD",
-@@ -136,7 +136,7 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -135,7 +135,7 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -39,7 +30,7 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
  	SPINAND_INFO("MX35LF1G24AD",
-@@ -146,16 +146,16 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -145,16 +145,16 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -59,7 +50,7 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
  	SPINAND_INFO("MX35LF4G24AD",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
-@@ -164,7 +164,7 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -163,7 +163,7 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -68,7 +59,7 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
  	SPINAND_INFO("MX31LF1GE4BC",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
-@@ -173,7 +173,7 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -172,7 +172,7 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -77,7 +68,7 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
  	SPINAND_INFO("MX31UF1GE4BC",
-@@ -183,7 +183,7 @@ static const struct spinand_info macronix_spinand_table[] = {
+@@ -182,7 +182,7 @@ static const struct spinand_info macronix_spinand_table[] = {
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
  					      &write_cache_variants,
  					      &update_cache_variants),
@@ -86,3 +77,6 @@
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
  				     mx35lf1ge4ab_ecc_get_status)),
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/450-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
similarity index 77%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/450-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
index b4fcfbc..2e888d3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/450-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
@@ -1,22 +1,15 @@
-From d3137043440fb1faaaf2481184f35b9ed0c1f2c2 Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:30 +0100
-Subject: [PATCH] mtd: spinand: micron: Generalize the OOB layout structure and
- function names
+From aebf853ada4f73280d4cf7a1799cb0ebf84f87e1 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:11 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch]
 
-In order to add new Micron SPI NAND devices, we generalized the OOB
-layout structure and function names.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-2-sshivamurthy@micron.com
 ---
  drivers/mtd/nand/spi/micron.c | 28 ++++++++++++++--------------
  1 file changed, 14 insertions(+), 14 deletions(-)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index f56f81325e10ac..cc1ee68421c8e1 100644
+index f56f81325..cc1ee6842 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -34,38 +34,38 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
@@ -81,3 +74,6 @@
  };
  
  static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
new file mode 100644
index 0000000..3ff682b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
@@ -0,0 +1,25 @@
+From 59766b3af8f603e740c38d2cc03c37226c78bb11 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:11 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch]
+
+---
+ drivers/mtd/nand/spi/micron.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
+index cc1ee6842..4727933c8 100644
+--- a/drivers/mtd/nand/spi/micron.c
++++ b/drivers/mtd/nand/spi/micron.c
+@@ -91,6 +91,7 @@ static int micron_8_ecc_get_status(struct spinand_device *spinand,
+ }
+ 
+ static const struct spinand_info micron_spinand_table[] = {
++	/* M79A 2Gb 3.3V */
+ 	SPINAND_INFO("MT29F2G01ABAGD",
+ 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/452-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
similarity index 75%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/452-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
index be3a3b1..4c5e911 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/452-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
@@ -1,20 +1,15 @@
-From a15335a17f4abf48ed9739c3b119232f9392cb60 Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:32 +0100
-Subject: [PATCH] mtd: spinand: micron: Add new Micron SPI NAND devices
+From 66ea40f7c5b196eee609c5e3322aac3a7ac59e03 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:12 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch]
 
-Add device table for M79A and M78A series Micron SPI NAND devices.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-4-sshivamurthy@micron.com
 ---
  drivers/mtd/nand/spi/micron.c | 33 +++++++++++++++++++++++++++++++++
  1 file changed, 33 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 4727933c894bc8..26925714a9fbac 100644
+index 4727933c8..26925714a 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -102,6 +102,39 @@ static const struct spinand_info micron_spinand_table[] = {
@@ -57,3 +52,6 @@
  };
  
  static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
new file mode 100644
index 0000000..ae7ac72
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
@@ -0,0 +1,61 @@
+From 65c3b878a33bb7edd5413860537fecdff94aaba6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:12 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch]
+
+---
+ drivers/mtd/nand/spi/micron.c | 16 ++++++++++++++++
+ include/linux/mtd/spinand.h   |  1 +
+ 2 files changed, 17 insertions(+)
+
+diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
+index 26925714a..956f7710a 100644
+--- a/drivers/mtd/nand/spi/micron.c
++++ b/drivers/mtd/nand/spi/micron.c
+@@ -18,6 +18,8 @@
+ #define MICRON_STATUS_ECC_4TO6_BITFLIPS	(3 << 4)
+ #define MICRON_STATUS_ECC_7TO8_BITFLIPS	(5 << 4)
+ 
++#define MICRON_CFG_CR			BIT(0)
++
+ static SPINAND_OP_VARIANTS(read_cache_variants,
+ 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+@@ -137,7 +139,21 @@ static const struct spinand_info micron_spinand_table[] = {
+ 				     micron_8_ecc_get_status)),
+ };
+ 
++static int micron_spinand_init(struct spinand_device *spinand)
++{
++	/*
++	 * M70A device series enable Continuous Read feature at Power-up,
++	 * which is not supported. Disable this bit to avoid any possible
++	 * failure.
++	 */
++	if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT)
++		return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0);
++
++	return 0;
++}
++
+ static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
++	.init = micron_spinand_init,
+ };
+ 
+ const struct spinand_manufacturer micron_spinand_manufacturer = {
+diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
+index f4c4ae871..1077c4572 100644
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -284,6 +284,7 @@ struct spinand_ecc_info {
+ };
+ 
+ #define SPINAND_HAS_QE_BIT		BIT(0)
++#define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+ 
+ /**
+  * struct spinand_info - Structure used to describe SPI NAND chips
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/454-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/454-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
index 158492f..426d674 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/454-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
@@ -1,20 +1,15 @@
-From a7e5daccc310c3b892ae5e598cadb7a9274c2547 Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:34 +0100
-Subject: [PATCH] mtd: spinand: micron: Add M70A series Micron SPI NAND devices
+From 5a4cd6ba8f7ae6744ca44f78c761f26e843c0341 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:12 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch]
 
-Add device table for M70A series Micron SPI NAND devices.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-6-sshivamurthy@micron.com
 ---
  drivers/mtd/nand/spi/micron.c | 22 ++++++++++++++++++++++
  1 file changed, 22 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 956f7710aca263..d6fd630087822c 100644
+index 956f7710a..d6fd63008 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -137,6 +137,28 @@ static const struct spinand_info micron_spinand_table[] = {
@@ -46,3 +41,6 @@
  };
  
  static int micron_spinand_init(struct spinand_device *spinand)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/455-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/455-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
index 8f8f1da..2e0a356 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/455-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
@@ -1,24 +1,15 @@
-From 9f9ae0c253c1e058fbc845e26c4a32a7d777f0dc Mon Sep 17 00:00:00 2001
-From: Shivamurthy Shastri <sshivamurthy@micron.com>
-Date: Wed, 11 Mar 2020 18:57:35 +0100
-Subject: [PATCH] mtd: spinand: micron: Add new Micron SPI NAND devices with
- multiple dies
+From ac7be09336555cf993d904bd9e42c05d1769288a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:12 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch]
 
-Add device table for new Micron SPI NAND devices, which have multiple
-dies.
-
-Also, enable support to select the dies.
-
-Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
-Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20200311175735.2007-7-sshivamurthy@micron.com
 ---
  drivers/mtd/nand/spi/micron.c | 58 +++++++++++++++++++++++++++++++++++
  1 file changed, 58 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index d6fd630087822c..5d370cfcdaaaa9 100644
+index d6fd63008..5d370cfcd 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -20,6 +20,14 @@
@@ -107,3 +98,6 @@
  };
  
  static int micron_spinand_init(struct spinand_device *spinand)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/456-mtd-spinand-micron-Use-more-specific-names.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch
similarity index 92%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/456-mtd-spinand-micron-Use-more-specific-names.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch
index ec03ffe..e397967 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/456-mtd-spinand-micron-Use-more-specific-names.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch
@@ -1,20 +1,15 @@
-From bdb84a22b02b0c2ca76bb3e3e16942338f67999b Mon Sep 17 00:00:00 2001
-From: Thirumalesha Narasimhappa <nthirumalesha7@gmail.com>
-Date: Sun, 8 Nov 2020 19:37:34 +0800
-Subject: [PATCH] mtd: spinand: micron: Use more specific names
+From 5abef195abf3faa6f8e22a2e6996316f14c4f21c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:13 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2324-mtd-spinand-micron-Use-more-specific-names.patch]
 
-Rename the read/write/update of SPINAND_OP_VARIANTS() to more
-specialized names.
-
-Signed-off-by: Thirumalesha Narasimhappa <nthirumalesha7@gmail.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20201108113735.2533-2-nthirumalesha7@gmail.com
 ---
  drivers/mtd/nand/spi/micron.c | 60 +++++++++++++++++------------------
  1 file changed, 30 insertions(+), 30 deletions(-)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 5d370cfcdaaaa9..afe3ba37dcfb8e 100644
+index 5d370cfcd..afe3ba37d 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -28,7 +28,7 @@
@@ -157,3 +152,6 @@
  		     SPINAND_HAS_CR_FEAT_BIT,
  		     SPINAND_ECCINFO(&micron_8_ooblayout,
  				     micron_8_ecc_get_status),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/457-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/457-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
index ecd2b71..b6914ce 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/457-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
@@ -1,20 +1,15 @@
-From 8c573d9419bf61f7b66b6114f1171f3a8a4a0e38 Mon Sep 17 00:00:00 2001
-From: Thirumalesha Narasimhappa <nthirumalesha7@gmail.com>
-Date: Sun, 8 Nov 2020 19:37:35 +0800
-Subject: [PATCH] mtd: spinand: micron: Add support for MT29F2G01AAAED
+From 5cea72055a3bce2b8b5a1f8cb6d46165eeccd8b9 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:13 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch]
 
-The MT29F2G01AAAED is a single die, 2Gb Micron SPI NAND Flash with 4-bit
-ECC
-
-Signed-off-by: Thirumalesha Narasimhappa <nthirumalesha7@gmail.com>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/20201108113735.2533-3-nthirumalesha7@gmail.com
 ---
  drivers/mtd/nand/spi/micron.c | 64 +++++++++++++++++++++++++++++++++++
  1 file changed, 64 insertions(+)
 
 diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index afe3ba37dcfb8e..50b7295bc92226 100644
+index afe3ba37d..50b7295bc 100644
 --- a/drivers/mtd/nand/spi/micron.c
 +++ b/drivers/mtd/nand/spi/micron.c
 @@ -44,6 +44,19 @@ static SPINAND_OP_VARIANTS(x4_update_cache_variants,
@@ -102,3 +97,6 @@
  };
  
  static int micron_spinand_init(struct spinand_device *spinand)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/470-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
similarity index 73%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/470-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
index 80672e6..74bab62 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/470-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
@@ -1,32 +1,18 @@
-From 6b49e58d6d9dab031a16af2af5439f28a37c4cd9 Mon Sep 17 00:00:00 2001
-From: Yoshio Furuyama <ytc-mb-yfuruyama7@kioxia.com>
-Date: Tue, 24 Mar 2020 15:49:44 +0900
-Subject: [PATCH] mtd: spinand: toshiba: Rename function name to change suffix
- and prefix (8Gbit)
+From af4301a675f4fcbaa787f1d3bd07df1c08a093c3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:13 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch]
 
-The suffix was changed from "G" to "J" to classify between 1st generation
-and 2nd generation serial NAND devices (which now belong to the Kioxia
-brand).
-As reference that's
-1st generation device of 1Gbit product is "TC58CVG0S3HRAIG"
-2nd generation device of 1Gbit product is "TC58CVG0S3HRAIJ".
-
-The 8Gbit type "TH58CxG3S0HRAIJ" is new to Kioxia's serial NAND lineup and
-the prefix was changed from "TC58" to "TH58".
-
-Thus the functions were renamed from tc58cxgxsx_*() to tx58cxgxsxraix_*().
-
-Signed-off-by: Yoshio Furuyama <ytc-mb-yfuruyama7@kioxia.com>
-Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/0dedd9869569a17625822dba87878254d253ba0e.1584949601.git.ytc-mb-yfuruyama7@kioxia.com
 ---
- drivers/mtd/nand/spi/toshiba.c | 60 +++++++++++++++++-----------------
- 1 file changed, 30 insertions(+), 30 deletions(-)
+ drivers/mtd/nand/spi/toshiba.c | 65 ++++++++++++++++++++--------------
+ 1 file changed, 38 insertions(+), 27 deletions(-)
 
+diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
+index 35da3c6e9..7ce5997dd 100644
 --- a/drivers/mtd/nand/spi/toshiba.c
 +++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -25,8 +25,8 @@ static SPINAND_OP_VARIANTS(write_cache_v
+@@ -25,8 +25,8 @@ static SPINAND_OP_VARIANTS(write_cache_variants,
  static SPINAND_OP_VARIANTS(update_cache_variants,
  		SPINAND_PROG_LOAD(false, 0, NULL, 0));
  
@@ -37,7 +23,7 @@
  {
  	if (section > 0)
  		return -ERANGE;
-@@ -37,8 +37,8 @@ static int tc58cxgxsx_ooblayout_ecc(stru
+@@ -37,8 +37,8 @@ static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
  	return 0;
  }
  
@@ -48,7 +34,7 @@
  {
  	if (section > 0)
  		return -ERANGE;
-@@ -50,13 +50,13 @@ static int tc58cxgxsx_ooblayout_free(str
+@@ -50,13 +50,13 @@ static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
  	return 0;
  }
  
@@ -67,7 +53,7 @@
  {
  	struct nand_device *nand = spinand_to_nand(spinand);
  	u8 mbf = 0;
-@@ -95,7 +95,7 @@ static int tc58cxgxsx_ecc_get_status(str
+@@ -95,7 +95,7 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
  
  static const struct spinand_info toshiba_spinand_table[] = {
  	/* 3.3V 1Gb */
@@ -76,7 +62,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -103,10 +103,10 @@ static const struct spinand_info toshiba
+@@ -103,10 +103,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -90,7 +76,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -114,10 +114,10 @@ static const struct spinand_info toshiba
+@@ -114,10 +114,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -104,7 +90,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -125,10 +125,21 @@ static const struct spinand_info toshiba
+@@ -125,10 +125,21 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -129,7 +115,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -136,10 +147,10 @@ static const struct spinand_info toshiba
+@@ -136,10 +147,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -143,7 +129,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -147,10 +158,10 @@ static const struct spinand_info toshiba
+@@ -147,10 +158,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -157,7 +143,7 @@
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
-@@ -158,8 +169,8 @@ static const struct spinand_info toshiba
+@@ -158,8 +169,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
@@ -168,3 +154,6 @@
  };
  
  static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/471-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
similarity index 85%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/471-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
index ffa1ad8..12a55cb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/471-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
@@ -1,25 +1,18 @@
-From 798fcdd010006e87b3154d6454c657af7b033002 Mon Sep 17 00:00:00 2001
-From: Yoshio Furuyama <ytc-mb-yfuruyama7@kioxia.com>
-Date: Tue, 24 Mar 2020 15:49:55 +0900
-Subject: [PATCH] mtd: spinand: toshiba: Support for new Kioxia Serial NAND
+From 1d16ff587875717c950c983af8eaa474d0a855ca Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:13 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch]
 
-Add support for new Kioxia products.
-The new Kioxia products support program load x4 command, and have
-HOLD_D bit which is equivalent to QE bit.
-
-Signed-off-by: Yoshio Furuyama <ytc-mb-yfuruyama7@kioxia.com>
-Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
-Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-Link: https://lore.kernel.org/linux-mtd/aa69e455beedc5ce0d7141359b9364ed8aec9e65.1584949601.git.ytc-mb-yfuruyama7@kioxia.com
 ---
  drivers/mtd/nand/spi/toshiba.c | 128 ++++++++++++++++++++++++++++-----
  1 file changed, 111 insertions(+), 17 deletions(-)
 
 diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
-index 5d217dd4b2539a..bc801d83343e5c 100644
+index 7ce5997dd..be51a2eaf 100644
 --- a/drivers/mtd/nand/spi/toshiba.c
 +++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -20,6 +20,18 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
+@@ -19,6 +19,18 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
  		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
  
@@ -38,7 +31,7 @@
  static SPINAND_OP_VARIANTS(write_cache_variants,
  		SPINAND_PROG_LOAD(true, 0, NULL, 0));
  
-@@ -95,7 +107,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
+@@ -94,7 +106,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
  }
  
  static const struct spinand_info toshiba_spinand_table[] = {
@@ -47,7 +40,7 @@
  	SPINAND_INFO("TC58CVG0S3HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-@@ -106,7 +118,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -105,7 +117,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -56,7 +49,7 @@
  	SPINAND_INFO("TC58CVG1S3HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-@@ -117,7 +129,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -116,7 +128,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -65,7 +58,7 @@
  	SPINAND_INFO("TC58CVG2S0HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-@@ -128,18 +140,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -127,18 +139,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -85,7 +78,7 @@
  	SPINAND_INFO("TC58CYG0S3HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-@@ -150,7 +151,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -149,7 +150,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -94,7 +87,7 @@
  	SPINAND_INFO("TC58CYG1S3HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
  		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-@@ -161,7 +162,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -160,7 +161,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -103,7 +96,7 @@
  	SPINAND_INFO("TC58CYG2S0HRAIG",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
  		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-@@ -172,6 +173,99 @@ static const struct spinand_info toshiba_spinand_table[] = {
+@@ -171,6 +172,99 @@ static const struct spinand_info toshiba_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
  				     tx58cxgxsxraix_ecc_get_status)),
@@ -203,3 +196,6 @@
  };
  
  static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/827-v5.16-spi-add-power-control-when-set_cs.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2360-v5.16-spi-add-power-control-when-set_cs.patch
similarity index 62%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/827-v5.16-spi-add-power-control-when-set_cs.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2360-v5.16-spi-add-power-control-when-set_cs.patch
index f3e7940..1016204 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/827-v5.16-spi-add-power-control-when-set_cs.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2360-v5.16-spi-add-power-control-when-set_cs.patch
@@ -1,14 +1,15 @@
-drivers: spi: backport PM improvement for SPI framework
+From 0078d23c468b3b3fd73d65f1652de0b355b95081 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:18 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2360-v5.16-spi-add-power-control-when-set_cs.patch]
 
-Fix PM improvement for SPI framework.
-As to set_cs takes effect immediately, power spi
-is needed when setup spi.
+---
+ drivers/spi/spi.c | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
 
-(cherry picked from commit d948e6ca189985495a21cd622c31e30e72b6b688)
-Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/spi/spi.c?h=v5.16-rc4&id=d948e6ca189985495a21cd622c31e30e72b6b688
-(cherry picked from commit 57a9460705f105e1d79d1410c5cfe285beda8986)
-Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/spi/spi.c?h=v5.16-rc4&id=57a9460705f105e1d79d1410c5cfe285beda8986
-
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 197a47eab..e562735a3 100644
 --- a/drivers/spi/spi.c
 +++ b/drivers/spi/spi.c
 @@ -3170,7 +3170,29 @@ int spi_setup(struct spi_device *spi)
@@ -43,5 +44,5 @@
  	if (spi->rt && !spi->controller->rt) {
  		spi->controller->rt = true;
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
new file mode 100644
index 0000000..d7fc25c
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
@@ -0,0 +1,176 @@
+From bc97a676615bd0ec66bb2a2a42c939455bf5bed6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:27 +0800
+Subject: [PATCH] 
+ [networking][999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch]
+
+---
+ drivers/net/phy/phy_device.c | 16 +++++----------
+ include/linux/iopoll.h       | 40 +++++++++++++++++++++++++++++-------
+ include/linux/phy.h          | 27 ++++++++++++++++++++++++
+ 3 files changed, 65 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index 76a68bb02..0349801df 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1056,18 +1056,12 @@ EXPORT_SYMBOL(phy_disconnect);
+ static int phy_poll_reset(struct phy_device *phydev)
+ {
+ 	/* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
+-	unsigned int retries = 12;
+-	int ret;
+-
+-	do {
+-		msleep(50);
+-		ret = phy_read(phydev, MII_BMCR);
+-		if (ret < 0)
+-			return ret;
+-	} while (ret & BMCR_RESET && --retries);
+-	if (ret & BMCR_RESET)
+-		return -ETIMEDOUT;
++	int ret, val;
+ 
++	ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
++				    50000, 600000, true);
++	if (ret)
++		return ret;
+ 	/* Some chips (smsc911x) may still need up to another 1ms after the
+ 	 * BMCR_RESET bit is cleared before they are usable.
+ 	 */
+diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
+index 35e15dfd4..cb20c733b 100644
+--- a/include/linux/iopoll.h
++++ b/include/linux/iopoll.h
+@@ -14,36 +14,41 @@
+ #include <linux/io.h>
+ 
+ /**
+- * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+- * @op: accessor function (takes @addr as its only argument)
+- * @addr: Address to poll
++ * read_poll_timeout - Periodically poll an address until a condition is
++ *			met or a timeout occurs
++ * @op: accessor function (takes @args as its arguments)
+  * @val: Variable to read the value into
+  * @cond: Break condition (usually involving @val)
+  * @sleep_us: Maximum time to sleep between reads in us (0
+  *            tight-loops).  Should be less than ~20ms since usleep_range
+  *            is used (see Documentation/timers/timers-howto.rst).
+  * @timeout_us: Timeout in us, 0 means never timeout
++ * @sleep_before_read: if it is true, sleep @sleep_us before read.
++ * @args: arguments for @op poll
+  *
+  * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+- * case, the last read value at @addr is stored in @val. Must not
++ * case, the last read value at @args is stored in @val. Must not
+  * be called from atomic context if sleep_us or timeout_us are used.
+  *
+  * When available, you'll probably want to use one of the specialized
+  * macros defined below rather than this macro directly.
+  */
+-#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)	\
++#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
++				sleep_before_read, args...) \
+ ({ \
+ 	u64 __timeout_us = (timeout_us); \
+ 	unsigned long __sleep_us = (sleep_us); \
+ 	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
+ 	might_sleep_if((__sleep_us) != 0); \
++	if (sleep_before_read && __sleep_us) \
++		usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+ 	for (;;) { \
+-		(val) = op(addr); \
++		(val) = op(args); \
+ 		if (cond) \
+ 			break; \
+ 		if (__timeout_us && \
+ 		    ktime_compare(ktime_get(), __timeout) > 0) { \
+-			(val) = op(addr); \
++			(val) = op(args); \
+ 			break; \
+ 		} \
+ 		if (__sleep_us) \
+@@ -52,6 +57,27 @@
+ 	(cond) ? 0 : -ETIMEDOUT; \
+ })
+ 
++/**
++ * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
++ * @op: accessor function (takes @addr as its only argument)
++ * @addr: Address to poll
++ * @val: Variable to read the value into
++ * @cond: Break condition (usually involving @val)
++ * @sleep_us: Maximum time to sleep between reads in us (0
++ *            tight-loops).  Should be less than ~20ms since usleep_range
++ *            is used (see Documentation/timers/timers-howto.rst).
++ * @timeout_us: Timeout in us, 0 means never timeout
++ *
++ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
++ * case, the last read value at @addr is stored in @val. Must not
++ * be called from atomic context if sleep_us or timeout_us are used.
++ *
++ * When available, you'll probably want to use one of the specialized
++ * macros defined below rather than this macro directly.
++ */
++#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)	\
++	read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
++
+ /**
+  * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs
+  * @op: accessor function (takes @addr as its only argument)
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index a1070d60e..107dcbea4 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -21,6 +21,7 @@
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
+ #include <linux/mod_devicetable.h>
++#include <linux/iopoll.h>
+ 
+ #include <linux/atomic.h>
+ 
+@@ -714,6 +715,19 @@ static inline int phy_read(struct phy_device *phydev, u32 regnum)
+ 	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
+ }
+ 
++#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
++				timeout_us, sleep_before_read) \
++({ \
++	int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \
++		sleep_us, timeout_us, sleep_before_read, phydev, regnum); \
++	if (val <  0) \
++		__ret = val; \
++	if (__ret) \
++		phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
++	__ret; \
++})
++
++
+ /**
+  * __phy_read - convenience function for reading a given PHY register
+  * @phydev: the phy_device struct
+@@ -766,6 +780,19 @@ static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val)
+  */
+ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
+ 
++#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
++				  sleep_us, timeout_us, sleep_before_read) \
++({ \
++	int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
++				  sleep_us, timeout_us, sleep_before_read, \
++				  phydev, devaddr, regnum); \
++	if (val <  0) \
++		__ret = val; \
++	if (__ret) \
++		phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
++	__ret; \
++})
++
+ /**
+  * __phy_read_mmd - Convenience function for reading a register
+  * from an MMD on a given PHY.
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
similarity index 66%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
index b47f2bf..e74f20b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
@@ -1,97 +1,20 @@
-From patchwork Wed May  6 14:53:13 2020
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Michael Walle <michael@walle.cc>
-X-Patchwork-Id: 1284481
-X-Patchwork-Delegate: davem@davemloft.net
-Return-Path: <netdev-owner@vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev@ozlabs.org
-Delivered-To: patchwork-incoming-netdev@ozlabs.org
-Authentication-Results: ozlabs.org;
- spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
- (client-ip=23.128.96.18; helo=vger.kernel.org;
- envelope-from=netdev-owner@vger.kernel.org; receiver=<UNKNOWN>)
-Authentication-Results: ozlabs.org;
- dmarc=none (p=none dis=none) header.from=walle.cc
-Authentication-Results: ozlabs.org;
-	dkim=pass (1024-bit key;
- secure) header.d=walle.cc header.i=@walle.cc header.a=rsa-sha256
- header.s=mail2016061301 header.b=m9HhLh3d;
-	dkim-atps=neutral
-Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
-	by ozlabs.org (Postfix) with ESMTP id 49HKQ62Q28z9sSG
-	for <patchwork-incoming-netdev@ozlabs.org>;
- Thu,  7 May 2020 00:55:10 +1000 (AEST)
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
-        id S1729301AbgEFOzD (ORCPT
-        <rfc822;patchwork-incoming-netdev@ozlabs.org>);
-        Wed, 6 May 2020 10:55:03 -0400
-Received: from ssl.serverraum.org ([176.9.125.105]:43029 "EHLO
-        ssl.serverraum.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
-        with ESMTP id S1729078AbgEFOzC (ORCPT
-        <rfc822;netdev@vger.kernel.org>); Wed, 6 May 2020 10:55:02 -0400
-Received: from apollo.fritz.box (unknown
- [IPv6:2a02:810c:c200:2e91:6257:18ff:fec4:ca34])
-        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
-         key-exchange ECDHE (P-384) server-signature RSA-PSS (2048 bits)
- server-digest SHA256)
-        (No client certificate requested)
-        by ssl.serverraum.org (Postfix) with ESMTPSA id 2354022EEB;
-        Wed,  6 May 2020 16:54:57 +0200 (CEST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=walle.cc;
- s=mail2016061301;
-        t=1588776897;
-        h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
-         to:to:cc:cc:mime-version:mime-version:
-         content-transfer-encoding:content-transfer-encoding:
-         in-reply-to:in-reply-to:references:references;
-        bh=Y1HXOD90+xthCbcF5aODRvO5s4y3GjqVZeWMcm2C9hg=;
-        b=m9HhLh3dnD9BTg85PIRYHxEzW+9tKI8srVGI3MjgXJkJaWDcnUKGyPN86orzkyHrB0ai5O
-        VyiY7R2tdN04JifV18FNmxuUW/9Pc3kWUfo+q974YzVhTm0Tkrc3osn/smhyhl7PxpHZMl
-        VHiTEHII3umwamTkGQq8kpYUr38joLY=
-From: Michael Walle <michael@walle.cc>
-To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
-Cc: Andrew Lunn <andrew@lunn.ch>,
-        Florian Fainelli <f.fainelli@gmail.com>,
-        Heiner Kallweit <hkallweit1@gmail.com>,
-        Russell King <linux@armlinux.org.uk>,
-        "David S . Miller" <davem@davemloft.net>,
-        Vladimir Oltean <vladimir.oltean@nxp.com>,
-        Antoine Tenart <antoine.tenart@bootlin.com>,
-        Michael Walle <michael@walle.cc>
-Subject: [PATCH net-next v3 1/3] net: phy: add concept of shared storage for
- PHYs
-Date: Wed,  6 May 2020 16:53:13 +0200
-Message-Id: <20200506145315.13967-2-michael@walle.cc>
-X-Mailer: git-send-email 2.20.1
-In-Reply-To: <20200506145315.13967-1-michael@walle.cc>
-References: <20200506145315.13967-1-michael@walle.cc>
-MIME-Version: 1.0
-X-Spam: Yes
-Sender: netdev-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev@vger.kernel.org
+From 2dca4de7282d3003f3703f707d773f4dbbc0f28e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:27 +0800
+Subject: [PATCH] 
+ [networking][999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch]
 
-There are packages which contain multiple PHY devices, eg. a quad PHY
-transceiver. Provide functions to allocate and free shared storage.
-
-Usually, a quad PHY contains global registers, which don't belong to any
-PHY. Provide convenience functions to access these registers.
-
-Signed-off-by: Michael Walle <michael@walle.cc>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
 ---
  drivers/net/phy/mdio_bus.c   |   1 +
  drivers/net/phy/phy_device.c | 138 +++++++++++++++++++++++++++++++++++
  include/linux/phy.h          |  89 ++++++++++++++++++++++
  3 files changed, 228 insertions(+)
 
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index fdf8221f4..d9f2cee33 100644
 --- a/drivers/net/phy/mdio_bus.c
 +++ b/drivers/net/phy/mdio_bus.c
-@@ -404,6 +404,7 @@ int __mdiobus_register(struct mii_bus *b
+@@ -404,6 +404,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
  	}
  
  	mutex_init(&bus->mdio_lock);
@@ -99,12 +22,15 @@
  
  	/* de-assert bus level PHY GPIO reset */
  	gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index 0349801df..99f265a1c 100644
 --- a/drivers/net/phy/phy_device.c
 +++ b/drivers/net/phy/phy_device.c
-@@ -1448,6 +1448,144 @@ bool phy_driver_is_genphy_10g(struct phy
+@@ -1447,6 +1447,144 @@ bool phy_driver_is_genphy_10g(struct phy_device *phydev)
+ }
  EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
  
- /**
++/**
 + * phy_package_join - join a common PHY group
 + * @phydev: target phy_device struct
 + * @addr: cookie and PHY address for global register access
@@ -242,10 +168,11 @@
 +}
 +EXPORT_SYMBOL_GPL(devm_phy_package_join);
 +
-+/**
+ /**
   * phy_detach - detach a PHY device from its network device
   * @phydev: target phy_device struct
-  *
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 107dcbea4..d26dba255 100644
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
 @@ -22,6 +22,7 @@
@@ -256,7 +183,7 @@
  
  #include <linux/atomic.h>
  
-@@ -208,6 +209,28 @@ struct sfp_bus;
+@@ -211,6 +212,28 @@ struct sfp_bus;
  struct sfp_upstream_ops;
  struct sk_buff;
  
@@ -285,7 +212,7 @@
  /*
   * The Bus class for PHYs.  Devices which provide access to
   * PHYs should register using this structure
-@@ -255,6 +278,12 @@ struct mii_bus {
+@@ -258,6 +281,12 @@ struct mii_bus {
  	int reset_delay_us;
  	/* RESET GPIO descriptor pointer */
  	struct gpio_desc *reset_gpiod;
@@ -298,7 +225,7 @@
  };
  #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
  
-@@ -434,6 +463,10 @@ struct phy_device {
+@@ -437,6 +466,10 @@ struct phy_device {
  	/* For use by PHYs to maintain extra state */
  	void *priv;
  
@@ -309,7 +236,7 @@
  	/* Interrupt and Polling infrastructure */
  	struct delayed_work state_queue;
  
-@@ -1232,6 +1265,10 @@ int phy_ethtool_get_link_ksettings(struc
+@@ -1242,6 +1275,10 @@ int phy_ethtool_get_link_ksettings(struct net_device *ndev,
  int phy_ethtool_set_link_ksettings(struct net_device *ndev,
  				   const struct ethtool_link_ksettings *cmd);
  int phy_ethtool_nway_reset(struct net_device *ndev);
@@ -320,7 +247,7 @@
  
  #if IS_ENABLED(CONFIG_PHYLIB)
  int __init mdio_bus_init(void);
-@@ -1284,6 +1321,58 @@ static inline int phy_ethtool_get_stats(
+@@ -1294,6 +1331,58 @@ static inline int phy_ethtool_get_stats(struct phy_device *phydev,
  	return 0;
  }
  
@@ -379,3 +306,6 @@
  extern struct bus_type mdio_bus_type;
  
  struct mdio_board_info {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
new file mode 100644
index 0000000..c2f2c10
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
@@ -0,0 +1,55 @@
+From 3fc10755d5f6a5618519f2b5b3a68febfc5984b0 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:27 +0800
+Subject: [PATCH] 
+ [networking][999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch]
+
+---
+ include/linux/phy.h | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index d26dba255..4f2c105f5 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -232,7 +232,8 @@ struct phy_package_shared {
+ };
+ 
+ /* used as bit number in atomic bitops */
+-#define PHY_SHARED_F_INIT_DONE 0
++#define PHY_SHARED_F_INIT_DONE  0
++#define PHY_SHARED_F_PROBE_DONE 1
+ 
+ /*
+  * The Bus class for PHYs.  Devices which provide access to
+@@ -1373,14 +1374,25 @@ static inline int __phy_package_write(struct phy_device *phydev,
+ 	return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
+ }
+ 
+-static inline bool phy_package_init_once(struct phy_device *phydev)
++static inline bool __phy_package_set_once(struct phy_device *phydev,
++					  unsigned int b)
+ {
+ 	struct phy_package_shared *shared = phydev->shared;
+ 
+ 	if (!shared)
+ 		return false;
+ 
+-	return !test_and_set_bit(PHY_SHARED_F_INIT_DONE, &shared->flags);
++	return !test_and_set_bit(b, &shared->flags);
++}
++
++static inline bool phy_package_init_once(struct phy_device *phydev)
++{
++	return __phy_package_set_once(phydev, PHY_SHARED_F_INIT_DONE);
++}
++
++static inline bool phy_package_probe_once(struct phy_device *phydev)
++{
++	return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE);
+ }
+ 
+ extern struct bus_type mdio_bus_type;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
similarity index 63%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
index 83df94a..3551935 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
@@ -1,17 +1,19 @@
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -92,6 +92,8 @@ obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c
- obj-$(CONFIG_LXT_PHY)		+= lxt.o
- obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
- obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
-+obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
-+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)	+= mediatek-ge-soc.o
- obj-$(CONFIG_MESON_GXL_PHY)	+= meson-gxl.o
- obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
- obj-$(CONFIG_MICREL_PHY)	+= micrel.o
+From 0e0b69abbc9fdba0bf1ea723cee71b2a2402559e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:28 +0800
+Subject: [PATCH] 
+ [networking][999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch]
+
+---
+ drivers/net/phy/Kconfig  | 17 +++++++++++++++++
+ drivers/net/phy/Makefile |  2 ++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 5eeccfee2..ec5c66d0a 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -507,6 +507,23 @@ config MESON_GXL_PHY
+@@ -512,6 +512,23 @@ config MESON_GXL_PHY
  	---help---
  	  Currently has a driver for the Amlogic Meson GXL Internal PHY
  
@@ -35,3 +37,19 @@
  config MICREL_PHY
  	tristate "Micrel PHYs"
  	---help---
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 437ff2a2c..f4feb0e3d 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -94,6 +94,8 @@ obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
+ obj-$(CONFIG_LXT_PHY)		+= lxt.o
+ obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
++obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
++obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)	+= mediatek-ge-soc.o
+ obj-$(CONFIG_MESON_GXL_PHY)	+= meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY)	+= micrel.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index aab01cf..23bf73b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -163,9 +163,7 @@
     file://406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch \
     file://407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch \
     file://407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch \
-    file://408-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch \
     file://410-mtd-fix-calculating-partition-end-address.patch \
-    file://411-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch \
     file://412-v5.19-mtd-call-of_platform_populate-for-MTD-partitions.patch \
     file://413-v6.0-mtd-next-mtd-core-introduce-of-support-for-dynamic-partitions.patch \
     file://414-v6.1-mtd-allow-getting-MTD-device-associated-with-a-speci.patch \
@@ -174,23 +172,7 @@
     file://417-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch \
     file://417-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch \
     file://420-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch \
-    file://430-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch \
     file://430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch \
-    file://431-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch \
-    file://432-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch \
-    file://433-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch \
-    file://434-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch \
-    file://435-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch \
-    file://450-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch \
-    file://451-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch \
-    file://452-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch \
-    file://453-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch \
-    file://454-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch \
-    file://455-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch \
-    file://456-mtd-spinand-micron-Use-more-specific-names.patch \
-    file://457-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch \
-    file://470-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch \
-    file://471-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch \
     file://600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch \
     file://601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch \
     file://602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch \
@@ -270,10 +252,6 @@
     file://780-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch \
     file://781-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch \
     file://781-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch \
-    file://790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch \
-    file://791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
-    file://792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch;apply=no \
-    file://793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch \
     file://800-v5.5-iio-imu-Add-support-for-the-FXOS8700-IMU.patch \
     file://800-v5.5-scsi-core-Add-sysfs-attributes-for-VPD-pages-0h-and-.patch \
     file://801-v5.19-nvmem-core-support-passing-DT-node-in-cell-info.patch \
@@ -304,7 +282,6 @@
     file://822-v6.2-0003-nvmem-u-boot-env-add-Broadcom-format-support.patch \
     file://825-v5.8-spi-rb4xx-null-pointer-bug-fix.patch \
     file://826-v5.8-spi-rb4xx-update-driver-to-be-device-tree-aware.patch \
-    file://827-v5.16-spi-add-power-control-when-set_cs.patch \
     file://831-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch \
     file://831-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch \
     file://831-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch \
@@ -320,5 +297,29 @@
     file://900-v5.9-0001-dt-bindings-Add-multicolor-class-dt-bindings-documen.patch \
     file://900-v5.9-0002-leds-Add-multicolor-ID-to-the-color-ID-list.patch \
     file://900-v5.9-0003-leds-add-RGB-color-option-as-that-is-different-from-.patch \
+    file://999-2210-v6.1-iio-adc-add-rtq6056-support.patch \
+    file://999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch \
+    file://999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch \
+    file://999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch \
+    file://999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch \
+    file://999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch \
+    file://999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch \
+    file://999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch \
+    file://999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch \
+    file://999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch \
+    file://999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch \
+    file://999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch \
+    file://999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch \
+    file://999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch \
+    file://999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch \
+    file://999-2324-mtd-spinand-micron-Use-more-specific-names.patch \
+    file://999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch \
+    file://999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch \
+    file://999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch \
+    file://999-2360-v5.16-spi-add-power-control-when-set_cs.patch \
+    file://999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch \
+    file://999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
+    file://999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch;apply=no \
+    file://999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch \
     file://999-update-uapi-header-files-for-bridger.patch \
     "
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/recipes-kernel/linux/linux-mediatek-5.4/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c
index 1ddcf67..1cafc91 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c
@@ -31,6 +31,7 @@
 
 #define CFERAM_NAME		"cferam"
 #define CFERAM_NAME_LEN		(sizeof(CFERAM_NAME) - 1)
+#define CFERAM_NAME_MAX_LEN	32
 #define KERNEL_NAME		"vmlinux.lz"
 #define KERNEL_NAME_LEN		(sizeof(KERNEL_NAME) - 1)
 #define OPENWRT_NAME		"1-openwrt"
@@ -157,17 +158,28 @@
 			 const struct mtd_partition **pparts,
 			 uint8_t *buf, loff_t off, loff_t size, bool cfe_part)
 {
+	struct device_node *mtd_node;
 	struct mtd_partition *parts;
 	loff_t cfe_off, kernel_off, rootfs_off;
 	unsigned int num_parts = BCM_WFI_PARTS, cur_part = 0;
+	const char *cferam_name = CFERAM_NAME;
+	size_t cferam_name_len;
 	int ret;
 
+	mtd_node = mtd_get_of_node(master);
+	if (mtd_node)
+		of_property_read_string(mtd_node, "brcm,cferam", &cferam_name);
+
+	cferam_name_len = strnlen(cferam_name, CFERAM_NAME_MAX_LEN);
+	if (cferam_name_len > 0)
+		cferam_name_len--;
+
 	if (cfe_part) {
 		num_parts++;
 		cfe_off = off;
 
-		ret = jffs2_find_file(master, buf, CFERAM_NAME,
-				      CFERAM_NAME_LEN, &cfe_off,
+		ret = jffs2_find_file(master, buf, cferam_name,
+				      cferam_name_len, &cfe_off,
 				      size - (cfe_off - off), NULL, NULL);
 		if (ret)
 			return ret;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/930-cmdline-boot-parameters.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch
similarity index 72%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/930-cmdline-boot-parameters.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch
index 6a6c8a6..eadc288 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/930-cmdline-boot-parameters.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch
@@ -1,6 +1,19 @@
+From 32fdf519125a828c6fbbbc8dfdfda22791e710e6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:24 +0800
+Subject: [PATCH] [adv-feature][999-2540-cmdline-boot-parameters.patch]
+
+---
+ kernel/Makefile     |  2 ++
+ kernel/boot_param.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 46 insertions(+)
+ create mode 100644 kernel/boot_param.c
+
+diff --git a/kernel/Makefile b/kernel/Makefile
+index d038b0de8..be219c6ca 100644
 --- a/kernel/Makefile
 +++ b/kernel/Makefile
-@@ -12,6 +12,8 @@ obj-y     = fork.o exec_domain.o panic.o
+@@ -12,6 +12,8 @@ obj-y     = fork.o exec_domain.o panic.o \
  	    notifier.o ksysfs.o cred.o reboot.o \
  	    async.o range.o smpboot.o ucount.o
  
@@ -9,7 +22,10 @@
  obj-$(CONFIG_MODULES) += kmod.o
  obj-$(CONFIG_MULTIUSER) += groups.o
  
---- a/kernel/boot_param.c
+diff --git a/kernel/boot_param.c b/kernel/boot_param.c
+new file mode 100644
+index 000000000..3dfe828bc
+--- /dev/null
 +++ b/kernel/boot_param.c
 @@ -0,0 +1,44 @@
 +/* SPDX-License-Identifier: BSD-3-Clause */
@@ -56,3 +72,6 @@
 +
 +static char env_part[BOOT_PARAM_STR_MAX_LEN];
 +module_param_string(env_part, env_part, BOOT_PARAM_STR_MAX_LEN, 0444);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
index 431e127..11b86e3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
@@ -41,5 +41,5 @@
     file://910-kobject_uevent.patch \
     file://911-kobject_add_broadcast_uevent.patch \
     file://921-always-create-console-node-in-initramfs.patch \
-    file://930-cmdline-boot-parameters.patch \
+    file://999-2540-cmdline-boot-parameters.patch \
     "
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/499-mtd-add-nmbm-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/499-mtd-add-nmbm-support.patch
deleted file mode 100644
index 5cbaae2..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/499-mtd-add-nmbm-support.patch
+++ /dev/null
@@ -1,21 +0,0 @@
---- a/drivers/mtd/Kconfig
-+++ b/drivers/mtd/Kconfig
-@@ -228,6 +228,8 @@ source "drivers/mtd/ubi/Kconfig"
- 
- source "drivers/mtd/hyperbus/Kconfig"
- 
-+source "drivers/mtd/nmbm/Kconfig"
-+
- source "drivers/mtd/composite/Kconfig"
- 
- endif # MTD
---- a/drivers/mtd/Makefile
-+++ b/drivers/mtd/Makefile
-@@ -33,5 +33,7 @@ obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor/
- obj-$(CONFIG_MTD_UBI)		+= ubi/
- obj-$(CONFIG_MTD_HYPERBUS)	+= hyperbus/
- 
-+obj-y				+= nmbm/
-+
- # Composite drivers must be loaded last
- obj-y				+= composite/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2328-mtd-add-nmbm-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2328-mtd-add-nmbm-support.patch
new file mode 100644
index 0000000..1ed432c
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2328-mtd-add-nmbm-support.patch
@@ -0,0 +1,38 @@
+From 648532e848587a525aa02add84b119844a4aabc3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:14 +0800
+Subject: [PATCH] [spi-and-storage][999-2328-mtd-add-nmbm-support.patch]
+
+---
+ drivers/mtd/Kconfig  | 2 ++
+ drivers/mtd/Makefile | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
+index 503f19763..3ed42b402 100644
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -228,6 +228,8 @@ source "drivers/mtd/ubi/Kconfig"
+ 
+ source "drivers/mtd/hyperbus/Kconfig"
+ 
++source "drivers/mtd/nmbm/Kconfig"
++
+ source "drivers/mtd/composite/Kconfig"
+ 
+ endif # MTD
+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
+index 147e79596..f27f66784 100644
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -33,5 +33,7 @@ obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor/
+ obj-$(CONFIG_MTD_UBI)		+= ubi/
+ obj-$(CONFIG_MTD_HYPERBUS)	+= hyperbus/
+ 
++obj-y				+= nmbm/
++
+ # Composite drivers must be loaded last
+ obj-y				+= composite/
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/500-ubi-add-configurable-rootdev.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2329-ubi-add-configurable-rootdev.patch
similarity index 66%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/500-ubi-add-configurable-rootdev.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2329-ubi-add-configurable-rootdev.patch
index e0102c7..1ee6142 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/500-ubi-add-configurable-rootdev.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2329-ubi-add-configurable-rootdev.patch
@@ -1,3 +1,15 @@
+From 27ae9a1b684cd183ccf6881d32710b8890113d20 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:14 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2329-ubi-add-configurable-rootdev.patch]
+
+---
+ drivers/mtd/ubi/block.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
+index 873f9cb24..33e969fd3 100644
 --- a/drivers/mtd/ubi/block.c
 +++ b/drivers/mtd/ubi/block.c
 @@ -97,6 +97,12 @@ static DEFINE_IDR(ubiblock_minor_idr);
@@ -13,7 +25,7 @@
  static int __init ubiblock_set_param(const char *val,
  				     const struct kernel_param *kp)
  {
-@@ -460,8 +466,9 @@ int ubiblock_create(struct ubi_volume_in
+@@ -460,8 +466,9 @@ int ubiblock_create(struct ubi_volume_info *vi)
  		 dev->ubi_num, dev->vol_id, vi->name);
  	mutex_unlock(&devices_mutex);
  
@@ -24,7 +36,7 @@
  	    ROOT_DEV == 0) {
  		pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n",
  			  dev->ubi_num, dev->vol_id, vi->name);
-@@ -681,7 +688,7 @@ static void __init ubiblock_create_auto_
+@@ -681,7 +688,7 @@ static void __init ubiblock_create_auto_rootfs(void)
  	struct ubi_volume_info vi;
  
  	for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) {
@@ -33,3 +45,6 @@
  		if (IS_ERR(desc))
  			continue;
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/613-netfilter_optional_tcp_window_check.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch
similarity index 69%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/613-netfilter_optional_tcp_window_check.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch
index f6a3a82..0aea6d3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/613-netfilter_optional_tcp_window_check.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch
@@ -1,11 +1,16 @@
-From: Felix Fietkau <nbd@nbd.name>
-Subject: netfilter: optional tcp window check
+From 1f85572a62a39799a9bac846d46965d9a57a1e24 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:28 +0800
+Subject: [PATCH] 
+ [networking][999-2704-netfilter_optional_tcp_window_check.patch]
 
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
 ---
- net/netfilter/nf_conntrack_proto_tcp.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
+ net/netfilter/nf_conntrack_proto_tcp.c  |  8 +++++++-
+ net/netfilter/nf_conntrack_standalone.c | 11 +++++++++++
+ 2 files changed, 18 insertions(+), 1 deletion(-)
 
+diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
+index aed967e2f..e219b6f34 100644
 --- a/net/netfilter/nf_conntrack_proto_tcp.c
 +++ b/net/netfilter/nf_conntrack_proto_tcp.c
 @@ -31,6 +31,9 @@
@@ -18,7 +23,7 @@
  /* "Be conservative in what you do,
      be liberal in what you accept from others."
      If it's non-zero, we mark only out of window RST segments as INVALID. */
-@@ -476,6 +479,9 @@ static bool tcp_in_window(const struct n
+@@ -476,6 +479,9 @@ static bool tcp_in_window(const struct nf_conn *ct,
  	s32 receiver_offset;
  	bool res, in_recv_win;
  
@@ -28,7 +33,7 @@
  	/*
  	 * Get the required data from the packet.
  	 */
-@@ -1139,7 +1145,7 @@ int nf_conntrack_tcp_packet(struct nf_co
+@@ -1139,7 +1145,7 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
  		 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
  		 timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
  		timeout = timeouts[TCP_CONNTRACK_UNACK];
@@ -37,6 +42,8 @@
  		 timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
  		timeout = timeouts[TCP_CONNTRACK_RETRANS];
  	else
+diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
+index 73415bf51..236954e4f 100644
 --- a/net/netfilter/nf_conntrack_standalone.c
 +++ b/net/netfilter/nf_conntrack_standalone.c
 @@ -25,6 +25,9 @@
@@ -57,7 +64,7 @@
  	__NF_SYSCTL_CT_LAST_SYSCTL,
  };
  
-@@ -969,6 +973,13 @@ static struct ctl_table nf_ct_sysctl_tab
+@@ -969,6 +973,13 @@ static struct ctl_table nf_ct_sysctl_table[] = {
  		.proc_handler   = proc_dointvec_jiffies,
  	},
  #endif
@@ -71,3 +78,6 @@
  	{}
  };
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
index 3ac355f..af11131 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
@@ -65,15 +65,12 @@
     file://496-dt-bindings-add-bindings-for-mtd-concat-devices.patch \
     file://497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch \
     file://498-mtd-mtdconcat-select-readwrite-function.patch \
-    file://499-mtd-add-nmbm-support.patch \
-    file://500-ubi-add-configurable-rootdev.patch \
     file://530-jffs2_make_lzma_available.patch \
     file://532-jffs2_eofdetect.patch \
     file://600-netfilter_conntrack_flush.patch \
     file://610-netfilter_match_bypass_default_checks.patch \
     file://611-netfilter_match_bypass_default_table.patch \
     file://612-netfilter_match_reduce_memory_access.patch \
-    file://613-netfilter_optional_tcp_window_check.patch \
     file://620-net_sched-codel-do-not-defer-queue-length-update.patch \
     file://630-packet_socket_type.patch \
     file://655-increase_skb_pad.patch \
@@ -123,4 +120,7 @@
     file://834-ledtrig-libata.patch \
     file://840-hwrng-bcm2835-set-quality-to-1000.patch \
     file://920-mangle_bootargs.patch \
+    file://999-2328-mtd-add-nmbm-support.patch \
+    file://999-2329-ubi-add-configurable-rootdev.patch \
+    file://999-2704-netfilter_optional_tcp_window_check.patch \
     "
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
index 820e8bb..81851a0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
@@ -124,9 +124,9 @@
 		#size-cells = <2>;
 		ranges;
 
-		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		/* 256 KiB reserved for ARM Trusted Firmware (BL31) */
 		secmon_reserved: secmon@43000000 {
-			reg = <0 0x43000000 0 0x30000>;
+			reg = <0 0x43000000 0 0x40000>;
 			no-map;
 		};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
index 96c68a5..6fcfa57 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
@@ -124,9 +124,9 @@
 		#size-cells = <2>;
 		ranges;
 
-		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		/* 256 KiB reserved for ARM Trusted Firmware (BL31) */
 		secmon_reserved: secmon@43000000 {
-			reg = <0 0x43000000 0 0x30000>;
+			reg = <0 0x43000000 0 0x40000>;
 			no-map;
 		};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index 820e8bb..81851a0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -124,9 +124,9 @@
 		#size-cells = <2>;
 		ranges;
 
-		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		/* 256 KiB reserved for ARM Trusted Firmware (BL31) */
 		secmon_reserved: secmon@43000000 {
-			reg = <0 0x43000000 0 0x30000>;
+			reg = <0 0x43000000 0 0x40000>;
 			no-map;
 		};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
index 96c68a5..6fcfa57 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -124,9 +124,9 @@
 		#size-cells = <2>;
 		ranges;
 
-		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		/* 256 KiB reserved for ARM Trusted Firmware (BL31) */
 		secmon_reserved: secmon@43000000 {
-			reg = <0 0x43000000 0 0x30000>;
+			reg = <0 0x43000000 0 0x40000>;
 			no-map;
 		};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index 98dc4df..9ef502b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -732,7 +732,7 @@
 			    "eint";
 		gpio-controller;
 		#gpio-cells = <2>;
-		gpio-ranges = <&pio 0 0 83>;
+		gpio-ranges = <&pio 0 0 84>;
 		interrupt-controller;
 		interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
index 9e2e9a9..2cf886c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
@@ -263,7 +263,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
index 201f9ee..bf2abb6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -102,7 +102,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
index d664a46..aa93f3c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -93,7 +93,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
index c7e83fd..b8fb6aa 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
@@ -127,7 +127,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
index cf117ca..0f94eea 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -182,6 +182,13 @@
 		compatible = "infineon,dps310";
 		reg = <0x77>;
 	};
+
+	rtq6056: rtq6056@40 {
+		compatible = "richtek,rtq6056";
+		reg = <0x40>;
+		shunt-resistor-micro-ohms = <10000>;
+		#io-channel-cells = <1>;
+	};
 };
 
 &spi0 {
@@ -258,7 +265,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
index a9fc3c5..70a7554 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -127,7 +127,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
index 2a24f7d..7f7ddfd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -73,6 +73,58 @@
 	};
 };
 
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
@@ -166,6 +218,13 @@
 		};
 	};
 
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
index fde3572..13e25e1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -213,7 +213,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
index 0941b06..3865bf8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
@@ -229,7 +229,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
index ba29680..8e5751b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
@@ -102,7 +102,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
index 133da0c..a681b8b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
@@ -93,7 +93,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
index 7721c07..6a7773f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
@@ -127,7 +127,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
index 06b5702..d7df193 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
@@ -247,7 +247,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
index 61cdf7b..4f281a3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
@@ -127,7 +127,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
index a86e77e..1b04950 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
@@ -223,7 +223,7 @@
 
 		conf {
 			groups = "mdc_mdio0";
-			drive-strength = <MTK_DRIVE_8mA>;
+			drive-strength = <MTK_DRIVE_10mA>;
 		};
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 9987630..1b5d356 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -41,8 +41,10 @@
 u32 hw_lro_norule_flush_cnt[MTK_HW_LRO_RING_NUM];
 u32 mtk_hwlro_stats_ebl;
 u32 dbg_show_level;
+u32 cur_rss_num;
 
-static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb;
+static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb,
+			     *proc_rss_ctrl;
 typedef int (*mtk_lro_dbg_func) (int par);
 
 struct mtk_eth_debug {
@@ -302,10 +304,10 @@
 	if (kstrtoul(token, 16, (unsigned long *)&value))
 		return -EINVAL;
 
-	pr_info("%s:phy=%d, reg=0x%x, val=0x%x\n", __func__,
+	pr_info("%s:phy=%d, reg=0x%lx, val=0x%lx\n", __func__,
 		0x1f, reg, value);
 	mt7530_mdio_w32(eth, reg, value);
-	pr_info("%s:phy=%d, reg=0x%x, val=0x%x confirm..\n", __func__,
+	pr_info("%s:phy=%d, reg=0x%lx, val=0x%x confirm..\n", __func__,
 		0x1f, reg, mt7530_mdio_r32(eth, reg));
 
 	return len;
@@ -350,12 +352,12 @@
 	if (kstrtoul(token, 16, (unsigned long *)&value))
 		return -EINVAL;
 
-	pr_info("%s:phy=%d, reg=0x%x, val=0x%x\n", __func__,
+	pr_info("%s:phy=%ld, reg=0x%lx, val=0x%lx\n", __func__,
 		phy, reg, value);
 
 	_mtk_mdio_write(eth, phy,  reg, value);
 
-	pr_info("%s:phy=%d, reg=0x%x, val=0x%x confirm..\n", __func__,
+	pr_info("%s:phy=%ld, reg=0x%lx, val=0x%x confirm..\n", __func__,
 		phy, reg, _mtk_mdio_read(eth, phy, reg));
 
 	return len;
@@ -369,7 +371,7 @@
 	int count = len;
 	unsigned long dbg_level = 0;
 
-	len = min(count, sizeof(buf) - 1);
+	len = min((size_t)count, sizeof(buf) - 1);
 	if (copy_from_user(buf, ptr, len))
 		return -EFAULT;
 
@@ -695,8 +697,6 @@
 
 int esw_cnt_read(struct seq_file *seq, void *v)
 {
-	unsigned int pkt_cnt = 0;
-	int i = 0;
 	struct mtk_eth *eth = g_eth;
 
 	gdm_cnt_read(eth);
@@ -1121,6 +1121,60 @@
 	.open = dbg_regs_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
+	.release = single_release
+};
+
+ssize_t rss_ctrl_write(struct file *file, const char __user *buffer,
+		       size_t count, loff_t *data)
+{
+	char buf[32];
+	char *p_buf;
+	char *p_token = NULL;
+	char *p_delimiter = " \t";
+	long num = 4;
+	u32 len = count;
+	int ret;
+
+	if (len >= sizeof(buf)) {
+		pr_info("Input handling fail!\n");
+		return -1;
+	}
+
+	if (copy_from_user(buf, buffer, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	p_buf = buf;
+	p_token = strsep(&p_buf, p_delimiter);
+	if (!p_token)
+		num = 4;
+	else
+		ret = kstrtol(p_token, 10, &num);
+
+	if (!mtk_rss_set_indr_tbl(g_eth, num))
+		cur_rss_num = num;
+
+	return count;
+}
+
+int rss_ctrl_read(struct seq_file *seq, void *v)
+{
+	pr_info("ADMA is using %d-RSS.\n", cur_rss_num);
+	return 0;
+}
+
+static int rss_ctrl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rss_ctrl_read, 0);
+}
+
+static const struct file_operations rss_ctrl_fops = {
+	.owner = THIS_MODULE,
+	.open = rss_ctrl_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = rss_ctrl_write,
 	.release = single_release
 };
 
@@ -1837,6 +1891,17 @@
 	if (!proc_dbg_regs)
 		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS);
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		proc_rss_ctrl =
+			proc_create(PROCREG_RSS_CTRL, 0, proc_reg_dir,
+				    &rss_ctrl_fops);
+		if (!proc_rss_ctrl)
+			pr_info("!! FAIL to create %s PROC !!\n",
+				PROCREG_RSS_CTRL);
+
+		cur_rss_num = g_eth->soc->rss_num;
+	}
+
 	if (g_eth->hwlro) {
 		proc_hw_lro_stats =
 			proc_create(PROCREG_HW_LRO_STATS, 0, proc_reg_dir,
@@ -1881,6 +1946,9 @@
 	if (proc_dbg_regs)
 		remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir);
 
+	if (proc_rss_ctrl)
+		remove_proc_entry(PROCREG_RSS_CTRL, proc_reg_dir);
+
 	if (g_eth->hwlro) {
 		if (proc_hw_lro_stats)
 			remove_proc_entry(PROCREG_HW_LRO_STATS, proc_reg_dir);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index ec7167b..3e7c137 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -61,6 +61,7 @@
 #define PROCREG_RXRING			"rx_ring"
 #define PROCREG_DIR			"mtketh"
 #define PROCREG_DBG_REGS		"dbg_regs"
+#define PROCREG_RSS_CTRL		"rss_ctrl"
 #define PROCREG_HW_LRO_STATS		"hw_lro_stats"
 #define PROCREG_HW_LRO_AUTO_TLB		"hw_lro_auto_tlb"
 #define PROCREG_RESET_EVENT		"reset_event"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
index 5ab74ad..66b4646 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
@@ -326,7 +326,7 @@
 {
 	static u32 err_cnt_qtx;
 	u32 err_flag = 0;
-	u32 i = 0, is_rx_fc = 0;
+	u32 is_rx_fc = 0;
 
 	u32 is_qfsm_hang = (mtk_r32(eth, MTK_QDMA_FSM) & 0xF00) != 0;
 	u32 is_qfwd_hang = mtk_r32(eth, MTK_QDMA_FWD_CNT) == 0;
@@ -624,7 +624,7 @@
 	switch (event) {
 	case MTK_WIFI_RESET_DONE:
 	case MTK_FE_STOP_TRAFFIC_DONE:
-		pr_info("%s rcv done event:%x\n", __func__, event);
+		pr_info("%s rcv done event:%lx\n", __func__, event);
 		mtk_rest_cnt--;
 		if(!mtk_rest_cnt) {
 			complete(&wait_ser_done);
@@ -642,7 +642,7 @@
 	case MTK_FE_STOP_TRAFFIC_DONE_FAIL:
 		mtk_stop_fail = true;
 		mtk_reset_flag = MTK_FE_START_RESET;
-		pr_info("%s rcv done event:%x\n", __func__, event);
+		pr_info("%s rcv done event:%lx\n", __func__, event);
 		complete(&wait_ser_done);
 		mtk_rest_cnt = mtk_wifi_num;
 		break;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 02f1d34..78ac67e 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1053,11 +1053,11 @@
 		/* fall through */
 	case PHY_INTERFACE_MODE_1000BASEX:
 		phylink_set(mask, 1000baseX_Full);
-		/* fall through; */
+		/* fall through */
 	case PHY_INTERFACE_MODE_2500BASEX:
 		phylink_set(mask, 2500baseX_Full);
 		phylink_set(mask, 2500baseT_Full);
-		/* fall through; */
+		/* fall through */
 	case PHY_INTERFACE_MODE_GMII:
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
@@ -3015,6 +3015,24 @@
 	return 0;
 }
 
+int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num)
+{
+	u32 i, config;
+
+	if (num <= 0 || num > MTK_RX_NAPI_NUM)
+		return -EOPNOTSUPP;
+
+	for (i = 0, config = 0; i < 16; i++) {
+		config <<= 2;
+		config |= (i % num);
+	}
+
+	for (i = 0; i < 8; i++)
+		mtk_w32(eth, config, MTK_RSS_INDR_TABLE_DW(i));
+
+	return 0;
+}
+
 static int mtk_rss_init(struct mtk_eth *eth)
 {
 	u32 val;
@@ -3045,14 +3063,7 @@
 	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
 
 	/* Select the size of indirection table */
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW0);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW1);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW2);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW3);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW4);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW5);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW6);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW7);
+	mtk_rss_set_indr_tbl(eth, eth->soc->rss_num);
 
 	/* Pause */
 	val |= MTK_RSS_CFG_REQ;
@@ -3972,8 +3983,6 @@
 static void mtk_pending_work(struct work_struct *work)
 {
 	struct mtk_eth *eth = container_of(work, struct mtk_eth, pending_work);
-	struct device_node *phy_node = NULL;
-	struct mtk_mac *mac = NULL;
 	int err, i = 0;
 	unsigned long restart = 0;
 	u32 val = 0;
@@ -4346,7 +4355,6 @@
 static int mtk_set_eee(struct net_device *dev, struct ethtool_eee *eee)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
-	struct mtk_eth *eth = mac->hw;
 
 	if (mac->type == MTK_GDM_TYPE) {
 		if (eee->tx_lpi_enabled && eee->tx_lpi_timer > 255)
@@ -4911,6 +4919,7 @@
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4927,6 +4936,7 @@
 	.required_clks = MT7621_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
@@ -4944,6 +4954,7 @@
 	.required_clks = MT7622_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4960,6 +4971,7 @@
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4977,6 +4989,7 @@
 	.required_clks = MT7629_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4994,6 +5007,7 @@
 	.required_clks = MT7986_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -5011,6 +5025,7 @@
 	.required_clks = MT7981_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -5028,6 +5043,7 @@
 	.required_clks = MT7988_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 4,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma_v2),
@@ -5044,6 +5060,7 @@
 	.required_clks = MT7628_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7465188..01e15fe 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -267,15 +267,8 @@
 #define MTK_RSS_CFG_REQ			BIT(2)
 #define MTK_RSS_IPV6_STATIC_HASH	(0x7 << 8)
 #define MTK_RSS_IPV4_STATIC_HASH	(0x7 << 12)
-#define MTK_RSS_INDR_TABLE_DW0		(MTK_PDMA_RSS_GLO_CFG + 0x50)
-#define MTK_RSS_INDR_TABLE_DW1		(MTK_PDMA_RSS_GLO_CFG + 0x54)
-#define MTK_RSS_INDR_TABLE_DW2		(MTK_PDMA_RSS_GLO_CFG + 0x58)
-#define MTK_RSS_INDR_TABLE_DW3		(MTK_PDMA_RSS_GLO_CFG + 0x5C)
-#define MTK_RSS_INDR_TABLE_DW4		(MTK_PDMA_RSS_GLO_CFG + 0x60)
-#define MTK_RSS_INDR_TABLE_DW5		(MTK_PDMA_RSS_GLO_CFG + 0x64)
-#define MTK_RSS_INDR_TABLE_DW6		(MTK_PDMA_RSS_GLO_CFG + 0x68)
-#define MTK_RSS_INDR_TABLE_DW7		(MTK_PDMA_RSS_GLO_CFG + 0x6C)
-#define MTK_RSS_INDR_TABLE_SIZE4	0x39393939
+#define MTK_RSS_INDR_TABLE_DW(x)	(MTK_PDMA_RSS_GLO_CFG + 0x50 +	\
+					 ((x) * 0x4))
 
 /* PDMA Global Configuration Register */
 #define MTK_PDMA_GLO_CFG	(PDMA_BASE + 0x204)
@@ -1535,7 +1528,7 @@
 		       MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
 		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \
 		       MTK_GMAC2_XGMII | MTK_MUX_GMAC2_TO_XGMII | MTK_RSS | \
-		       MTK_NETSYS_RX_V2)
+		       MTK_NETSYS_RX_V2 | MTK_8GB_ADDRESSING)
 
 struct mtk_tx_dma_desc_info {
 	dma_addr_t	addr;
@@ -1614,6 +1607,7 @@
 struct mtk_soc_data {
 	const struct mtk_reg_map *reg_map;
 	u32		ana_rgc3;
+	u32		rss_num;
 	u64		caps;
 	u64		required_clks;
 	bool		required_pctl;
@@ -1870,4 +1864,5 @@
 int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
 
 void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num);
 #endif /* MTK_ETH_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 95e5e3c..05f4955 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -825,6 +825,9 @@
 mtk_hnat_ipv4_nf_pre_routing(void *priv, struct sk_buff *skb,
 			     const struct nf_hook_state *state)
 {
+	struct flow_offload_hw_path hw_path = { .dev = skb->dev,
+						.virt_dev = skb->dev };
+
 	if (!skb)
 		goto drop;
 
@@ -835,6 +838,19 @@
 
 	hnat_set_head_frags(state, skb, -1, hnat_set_iif);
 
+	/*
+	 * Avoid mistakenly binding of outer IP, ports in SW L2TP decap flow.
+	 * In pre-routing, if dev is virtual iface, TOPS module is not loaded,
+	 * and it's L2TP flow, then do not bind.
+	 */
+	if (skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
+	    && skb->dev->netdev_ops->ndo_flow_offload_check) {
+		skb->dev->netdev_ops->ndo_flow_offload_check(&hw_path);
+
+		if (hw_path.flags & FLOW_OFFLOAD_PATH_TNL)
+			skb_hnat_alg(skb) = 1;
+	}
+
 	pre_routing_print(skb, state->in, state->out, __func__);
 
 	/* packets from external devices -> xxx ,step 1 , learning stage & bound stage*/
@@ -964,10 +980,20 @@
 	struct neighbour *neigh = NULL;
 	struct dst_entry *dst = skb_dst(skb);
 	struct ethhdr *eth;
+	u16 eth_pppoe_hlen = ETH_HLEN + PPPOE_SES_HLEN;
 
 	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE) {
-		memcpy(eth_hdr(skb)->h_source, hw_path->eth_src, ETH_ALEN);
-		memcpy(eth_hdr(skb)->h_dest, hw_path->eth_dest, ETH_ALEN);
+		if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP) {
+			eth = (struct ethhdr *)(skb->data - eth_pppoe_hlen);
+			eth->h_proto = skb->protocol;
+			ether_addr_copy(eth->h_dest, hw_path->eth_dest);
+			ether_addr_copy(eth->h_source,  hw_path->eth_src);
+		} else {
+			eth = eth_hdr(skb);
+			memcpy(eth->h_source, hw_path->eth_src, ETH_ALEN);
+			memcpy(eth->h_dest, hw_path->eth_dest, ETH_ALEN);
+		}
+
 		return 0;
 	}
 
@@ -1150,6 +1176,20 @@
 	return entry;
 }
 
+static struct ethhdr *get_ipv6_ipip_ethhdr(struct sk_buff *skb,
+					   struct flow_offload_hw_path *hw_path)
+{
+	struct ethhdr *eth;
+	u16 eth_pppoe_hlen = ETH_HLEN + PPPOE_SES_HLEN;
+
+	if (hw_path->flags & FLOW_OFFLOAD_PATH_PPPOE)
+		eth = (struct ethhdr *)(skb->data - eth_pppoe_hlen);
+	else
+		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
+
+	return eth;
+}
+
 static unsigned int skb_to_hnat_info(struct sk_buff *skb,
 				     const struct net_device *dev,
 				     struct foe_entry *foe,
@@ -1174,7 +1214,7 @@
 
 	if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP)
 		/* point to ethernet header for DS-Lite and MapE */
-		eth = (struct ethhdr *)(skb->data - ETH_HLEN);
+		eth = get_ipv6_ipip_ethhdr(skb, hw_path);
 	else
 		eth = eth_hdr(skb);
 
@@ -1416,6 +1456,11 @@
 			break;
 
 		case NEXTHDR_IPIP:
+			iph = (struct iphdr *)skb_inner_network_header(skb);
+			/* don't process inner fragment packets */
+			if (ip_is_fragment(iph))
+				return 0;
+
 			if ((!mape_toggle &&
 			     entry.bfib1.pkt_type == IPV4_DSLITE) ||
 			    (mape_toggle &&
@@ -2444,6 +2489,10 @@
 	if (unlikely(!skb_hnat_is_hashed(skb)))
 		return 0;
 
+	/* Do not bind if pkt is fragmented */
+	if (ip_is_fragment(ip_hdr(skb)))
+		return 0;
+
 	if (out->netdev_ops->ndo_flow_offload_check) {
 		out->netdev_ops->ndo_flow_offload_check(&hw_path);
 		out = (IS_GMAC1_MODE) ? hw_path.virt_dev : hw_path.dev;
@@ -2491,7 +2540,7 @@
 			entry->ipv4_hnapt.m_timestamp = foe_timestamp(hnat_priv);
 
 		if (entry_hnat_is_bound(entry)) {
-			memset(skb_hnat_info(skb), 0, FOE_INFO_LEN);
+			memset(skb_hnat_info(skb), 0, sizeof(struct hnat_desc));
 
 			return -1;
 		}
@@ -2551,6 +2600,9 @@
 							  sizeof(_ports), &_ports);
 				if (unlikely(!pptr))
                                         return NF_ACCEPT;
+				/* don't process inner fragment packets */
+				if (ip_is_fragment(iph))
+					return NF_ACCEPT;
 
 				entry->bfib1.udp = udp;
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index c2acab2..3cc8f90 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -440,22 +440,18 @@
 		sgm_mode = SGMII_IF_MODE_SGMII |
 			   SGMII_REMOTE_FAULT_DIS |
 			   SGMII_SPEED_DUPLEX_AN;
-	} else if (phylink_autoneg_inband(mode)) {
-		/* 1000base-X or HSGMII with autoneg */
-		if (interface == PHY_INTERFACE_MODE_2500BASEX)
-			return -EINVAL;
-
+	} else if (interface == PHY_INTERFACE_MODE_2500BASEX) {
+		/* HSGMII without autoneg */
+		speed = SGMII_SPEED_1000;
+		sgm_mode = SGMII_IF_MODE_SGMII;
+	} else {
+		/* 1000base-X with/without autoneg */
 		bmcr = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 					 advertising) ? SGMII_AN_ENABLE : 0;
 		if (bmcr)
 			sgm_mode = SGMII_SPEED_DUPLEX_AN;
 		else
 			speed = SGMII_SPEED_1000;
-	} else {
-		/* 1000base-X or HSGMII without autoneg */
-		speed = SGMII_SPEED_1000;
-		if (interface == PHY_INTERFACE_MODE_2500BASEX)
-			sgm_mode = SGMII_IF_MODE_SGMII;
 	}
 
 	if (mpcs->interface != interface ||
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
index e6007f6..a181fc2 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
@@ -792,7 +792,8 @@
 	unsigned int cur = offset;
 	unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0;
 
-	pr_info("\n============ %s ============ pmap:%x\n", name, pmap);
+	pr_info("\n============ %s ============ pmap:%lx\n",
+		name, (unsigned long)pmap);
 	while (cur < offset + range) {
 		regmap_read(pmap, cur, &val1);
 		regmap_read(pmap, cur + 0x4, &val2);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index 2825a36..1047943 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -222,10 +222,20 @@
 	if (ret < 0)
 		return ret;
 	phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF;
+	/* FIXME: The current firmware always enables rate adaptation mode. */
+	phydev->rate_matching = RATE_MATCH_PAUSE;
 
 	return 0;
 }
 
+static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
+					      phy_interface_t iface)
+{
+	if (iface == PHY_INTERFACE_MODE_XGMII)
+		return RATE_MATCH_PAUSE;
+	return RATE_MATCH_NONE;
+}
+
 static struct phy_driver mtk_gephy_driver[] = {
 	{
 		PHY_ID_MATCH_EXACT(0x00339c11),
@@ -234,6 +244,7 @@
 		.config_aneg    = mt798x_2p5ge_phy_config_aneg,
 		.get_features	= mt798x_2p5ge_phy_get_features,
 		.read_status	= mt798x_2p5ge_phy_read_status,
+		.get_rate_matching	= mt798x_2p5ge_phy_get_rate_matching,
 		//.config_intr	= genphy_no_config_intr,
 		//.handle_interrupt = genphy_no_ack_interrupt,
 		//.suspend	= genphy_suspend,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
index f25fb8e..489e524 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
@@ -502,7 +502,7 @@
 	u16 reg, val;
 
 	if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
-		bias = -2;
+		bias = -1;
 
 	val = clamp_val(bias + tx_r50_cal_val, 0, 63);
 
@@ -718,6 +718,11 @@
 static void mt798x_phy_common_finetune(struct phy_device *phydev)
 {
 	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+	/* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+	__phy_write(phydev, 0x11, 0xc71);
+	__phy_write(phydev, 0x12, 0xc);
+	__phy_write(phydev, 0x10, 0x8fae);
+
 	/* EnabRandUpdTrig = 1 */
 	__phy_write(phydev, 0x11, 0x2f00);
 	__phy_write(phydev, 0x12, 0xe);
@@ -728,15 +733,56 @@
 	__phy_write(phydev, 0x12, 0x0);
 	__phy_write(phydev, 0x10, 0x83aa);
 
+	/* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
+	__phy_write(phydev, 0x11, 0x240);
+	__phy_write(phydev, 0x12, 0x0);
+	__phy_write(phydev, 0x10, 0x9680);
+
-	/* TrFreeze = 0 */
+	/* TrFreeze = 0 (mt7988 default) */
 	__phy_write(phydev, 0x11, 0x0);
 	__phy_write(phydev, 0x12, 0x0);
 	__phy_write(phydev, 0x10, 0x9686);
 
+	/* SSTrKp100 = 5 */
+	/* SSTrKf100 = 6 */
+	/* SSTrKp1000Mas = 5 */
+	/* SSTrKf1000Mas = 6 */
 	/* SSTrKp1000Slv = 5 */
+	/* SSTrKf1000Slv = 6 */
 	__phy_write(phydev, 0x11, 0xbaef);
 	__phy_write(phydev, 0x12, 0x2e);
 	__phy_write(phydev, 0x10, 0x968c);
+	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt7981_phy_finetune(struct phy_device *phydev)
+{
+	u16 val[8] = { 0x01ce, 0x01c1,
+		       0x020f, 0x0202,
+		       0x03d0, 0x03c0,
+		       0x0013, 0x0005 };
+	int i, k;
+
+	/* 100M eye finetune:
+	 * Keep middle level of TX MLT3 shapper as default.
+	 * Only change TX MLT3 overshoot level here.
+	 */
+	for (k = 0, i = 1; i < 12; i++) {
+		if (i % 3 == 0)
+			continue;
+		phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
+	}
+
+	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+	/* ResetSyncOffset = 6 */
+	__phy_write(phydev, 0x11, 0x600);
+	__phy_write(phydev, 0x12, 0x0);
+	__phy_write(phydev, 0x10, 0x8fc0);
+
+	/* VgaDecRate = 1 */
+	__phy_write(phydev, 0x11, 0x4c2a);
+	__phy_write(phydev, 0x12, 0x3e);
+	__phy_write(phydev, 0x10, 0x8fa4);
 
 	/* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
 	 * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
@@ -751,7 +797,7 @@
 	__phy_write(phydev, 0x10, 0x8ec0);
 	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
 
-	/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
+	/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
 	phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
 		       MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
 		       BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
@@ -782,48 +828,7 @@
 	phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
 	/* Adjust LDO output voltage */
 	phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
-}
 
-static void mt7981_phy_finetune(struct phy_device *phydev)
-{
-	u16 val[8] = { 0x01ce, 0x01c1,
-		       0x020f, 0x0202,
-		       0x03d0, 0x03c0,
-		       0x0013, 0x0005 };
-	int i, k;
-
-	/* 100M eye finetune:
-	 * Keep middle level of TX MLT3 shapper as default.
-	 * Only change TX MLT3 overshoot level here.
-	 */
-	for (k = 0, i = 1; i < 12; i++) {
-		if (i % 3 == 0)
-			continue;
-		phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
-	}
-
-	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
-	/* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
-	__phy_write(phydev, 0x11, 0xc71);
-	__phy_write(phydev, 0x12, 0xc);
-	__phy_write(phydev, 0x10, 0x8fae);
-
-	/* ResetSyncOffset = 6 */
-	__phy_write(phydev, 0x11, 0x600);
-	__phy_write(phydev, 0x12, 0x0);
-	__phy_write(phydev, 0x10, 0x8fc0);
-
-	/* VgaDecRate = 1 */
-	__phy_write(phydev, 0x11, 0x4c2a);
-	__phy_write(phydev, 0x12, 0x3e);
-	__phy_write(phydev, 0x10, 0x8fa4);
-
-	/* FfeUpdGainForce = 4 */
-	__phy_write(phydev, 0x11, 0x240);
-	__phy_write(phydev, 0x12, 0x0);
-	__phy_write(phydev, 0x10, 0x9680);
-
-	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
 }
 
 static void mt7988_phy_finetune(struct phy_device *phydev)
@@ -845,12 +850,6 @@
 		       MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
 
 	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
-
-	/* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
-	__phy_write(phydev, 0x11, 0x671);
-	__phy_write(phydev, 0x12, 0xc);
-	__phy_write(phydev, 0x10, 0x8fae);
-
 	/* ResetSyncOffset = 5 */
 	__phy_write(phydev, 0x11, 0x500);
 	__phy_write(phydev, 0x12, 0x0);
@@ -858,13 +857,28 @@
 
 	/* VgaDecRate is 1 at default on mt7988 */
 
-	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+	/* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
+	 * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
+	 */
+	__phy_write(phydev, 0x11, 0xb90a);
+	__phy_write(phydev, 0x12, 0x6f);
+	__phy_write(phydev, 0x10, 0x8f82);
+
+	/* RemAckCntLimitCtrl = 1 */
+	__phy_write(phydev, 0x11, 0xfbba);
+	__phy_write(phydev, 0x12, 0xc3);
+	__phy_write(phydev, 0x10, 0x87f8);
 
-	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
-	/* TxClkOffset = 2 */
-	__phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
-		     FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
 	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+	/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
+	phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+		       MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+		       BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
+
+	/* rg_tr_lpf_cnt_val = 1023 */
+	phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff);
+
 }
 
 static void mt798x_phy_eee(struct phy_device *phydev)
@@ -897,11 +911,11 @@
 		       MTK_PHY_LPI_SLV_SEND_TX_EN,
 		       FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
 
-	phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
-		       MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
-		       MTK_PHY_LPI_TXPCS_LOC_RCV,
-		       FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
+	/* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */
+	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
+			   MTK_PHY_LPI_TXPCS_LOC_RCV);
 
+	/* This also fixes some IoT issues, such as CH340 */
 	phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
 		       MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
 		       FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
@@ -935,7 +949,7 @@
 	__phy_write(phydev, 0x12, 0x0);
 	__phy_write(phydev, 0x10, 0x9690);
 
-	/* REG_EEE_st2TrKf1000 = 3 */
+	/* REG_EEE_st2TrKf1000 = 2 */
 	__phy_write(phydev, 0x11, 0x114f);
 	__phy_write(phydev, 0x12, 0x2);
 	__phy_write(phydev, 0x10, 0x969a);
@@ -960,7 +974,7 @@
 	__phy_write(phydev, 0x12, 0x0);
 	__phy_write(phydev, 0x10, 0x96b8);
 
-	/* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
+	/* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
 	__phy_write(phydev, 0x11, 0x1463);
 	__phy_write(phydev, 0x12, 0x0);
 	__phy_write(phydev, 0x10, 0x96ca);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c
index d685328..49c0be1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c
@@ -817,7 +817,7 @@
 static int mt7988_i2c2_0_pins[] = { 69, 70 };
 static int mt7988_i2c2_0_funcs[] = { 4, 4 };
 
-static int mt7988_i2c2_1_pins[] = { 70, 71 };
+static int mt7988_i2c2_1_pins[] = { 71, 72 };
 static int mt7988_i2c2_1_funcs[] = { 1, 1 };
 
 /* eth */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/1004-mtketh-add-threaded-napi-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-mtketh-add-threaded-napi-support.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/1004-mtketh-add-threaded-napi-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-mtketh-add-threaded-napi-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/1007-mtketh-add-qdma-sw-solution-for-mac80211-sdk.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mtketh-add-qdma-sw-solution-for-mac80211-sdk.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/1007-mtketh-add-qdma-sw-solution-for-mac80211-sdk.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mtketh-add-qdma-sw-solution-for-mac80211-sdk.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8011-ovs-add-multicast-to-unicast-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-ovs-add-multicast-to-unicast-support.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8011-ovs-add-multicast-to-unicast-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-ovs-add-multicast-to-unicast-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-mt7622-backport-nf-hw-offload-framework-and-ups.patch
similarity index 99%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-mt7622-backport-nf-hw-offload-framework-and-ups.patch
index 17f2cb1..b52782f 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-mt7622-backport-nf-hw-offload-framework-and-ups.patch
@@ -135,33 +135,33 @@
  	.required_pctl = true,
  	.has_sram = false,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 @@ -4424,6 +4444,7 @@ static const struct mtk_soc_data mt7621_
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 @@ -4439,6 +4460,7 @@ static const struct mtk_soc_data mt7622_
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 @@ -4453,6 +4475,7 @@ static const struct mtk_soc_data mt7623_
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index b6380ffeb..349f98503 100755
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1266,7 +1266,7 @@
 index 000000000..4294f0c74
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -0,0 +1,541 @@
+@@ -0,0 +1,535 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/*
 + *  Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
@@ -1735,14 +1735,11 @@
 +{
 +	struct mtk_mac *mac = netdev_priv(dev);
 +	struct mtk_eth *eth = mac->hw;
-+	struct nf_flowtable *flowtable;
 +	static LIST_HEAD(block_cb_list);
 +	struct flow_block_cb *block_cb;
 +	flow_setup_cb_t *cb;
 +	int err = 0;
 +
-+	flowtable = container_of(f->block, struct nf_flowtable, flow_block);
-+
 +	if (!eth->ppe.foe_table)
 +		return -EOPNOTSUPP;
 +
@@ -1752,8 +1749,6 @@
 +	cb = mtk_eth_setup_tc_block_cb;
 +	f->driver_block_list = &block_cb_list;
 +
-+	down_write(&flowtable->flow_block_lock);
-+
 +	switch (f->command) {
 +	case FLOW_BLOCK_BIND:
 +		block_cb = flow_block_cb_lookup(f->block, cb, dev);
@@ -1788,7 +1783,6 @@
 +	}
 +
 +unlock:
-+	up_write(&flowtable->flow_block_lock);
 +	return err;
 +}
 +
@@ -4922,7 +4916,7 @@
 index 000000000..d94c6fb92
 --- /dev/null
 +++ b/net/netfilter/nf_flow_table_offload.c
-@@ -0,0 +1,1197 @@
+@@ -0,0 +1,1199 @@
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/module.h>
@@ -5766,7 +5760,7 @@
 +	if (cmd == FLOW_CLS_REPLACE)
 +		cls_flow.rule = flow_rule->rule;
 +
-+	down_write(&flowtable->flow_block_lock);
++	down_read(&flowtable->flow_block_lock);
 +	list_for_each_entry(block_cb, block_cb_list, list) {
 +		err = block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow,
 +				   block_cb->cb_priv);
@@ -5775,7 +5769,7 @@
 +
 +		i++;
 +	}
-+	up_write(&flowtable->flow_block_lock);
++	up_read(&flowtable->flow_block_lock);
 +
 +	if (cmd == FLOW_CLS_STATS)
 +		memcpy(stats, &cls_flow.stats, sizeof(*stats));
@@ -5994,7 +5988,7 @@
 +	struct flow_block_cb *block_cb, *next;
 +	int err = 0;
 +
-+	down_read(&flowtable->flow_block_lock);
++	down_write(&flowtable->flow_block_lock);
 +
 +	switch (cmd) {
 +	case FLOW_BLOCK_BIND:
@@ -6011,7 +6005,7 @@
 +		err = -EOPNOTSUPP;
 +	}
 +
-+	up_read(&flowtable->flow_block_lock);
++	up_write(&flowtable->flow_block_lock);
 +
 +	return err;
 +}
@@ -6057,7 +6051,9 @@
 +
 +	nf_flow_table_block_offload_init(bo, dev_net(dev), cmd, flowtable,
 +					 extack);
++	down_write(&flowtable->flow_block_lock);
 +	err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, bo);
++	up_write(&flowtable->flow_block_lock);
 +	if (err < 0)
 +		return err;
 +
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9992-dts-mt7986-wed-changes.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-dts-mt7986-wed-changes.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9992-dts-mt7986-wed-changes.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-dts-mt7986-wed-changes.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-add-wed.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-add-wed.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-ethernet-update-ppe-from-mt7622-to-mt7986.patch
similarity index 99%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-ethernet-update-ppe-from-mt7622-to-mt7986.patch
index 033f588..c0efd12 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-ethernet-update-ppe-from-mt7622-to-mt7986.patch
@@ -51,6 +51,7 @@
  	.required_pctl = false,
  	.has_sram = true,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
  		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -60,7 +61,6 @@
  	},
  };
  
- static const struct mtk_soc_data mt7981_data = {
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index b52378bd6..fce1a7172 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
similarity index 98%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index 5d6f0d1..954c6e2 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -165,7 +165,7 @@
  	struct rhashtable		flow_table;
  };
  
-@@ -1668,8 +1674,10 @@ int mtk_gmac_usxgmii_path_setup(struct m
+@@ -1668,9 +1674,11 @@ int mtk_gmac_usxgmii_path_setup(struct m
  void mtk_usxgmii_reset(struct mtk_xgmii *ss, int mac_id);
  int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
  
@@ -174,6 +174,7 @@
  int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
  		     void *type_data);
  void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+ int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num);
 +
 +int mtk_ppe_debugfs_init(struct mtk_eth *eth);
  #endif /* MTK_ETH_H */
@@ -429,15 +430,13 @@
  	f->stats.lastused = jiffies - idle * HZ;
  
  	return 0;
-@@ -540,12 +564,14 @@ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
+@@ -540,10 +564,12 @@ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
  	static LIST_HEAD(block_cb_list);
  	struct flow_block_cb *block_cb;
  	flow_setup_cb_t *cb;
 -	int err = 0;
 +	int i, err = 0;
  
- 	flowtable = container_of(f->block, struct nf_flowtable, flow_block);
- 
 -	if (!eth->ppe || !eth->ppe->foe_table)
 -		return -EOPNOTSUPP;
 +	for (i = 0; i < eth->ppe_num; i++) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-tx-support-for-mt7986.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-tx-support-for-mt7986.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-wds-support-for-mt7986.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-tx-wds-support-for-mt7986.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-wds-support-for-mt7986.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-tx-wds-support-for-mt7986.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-add-wed-rx-support-for-mt7896.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-add-wed-rx-support-for-mt7896.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-add-wed-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-add-wed-ser-support.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-add-wed-ser-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-add-wed-ser-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-1-ethernet-update-ppe-backward-compatible-two-way-hash.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-ethernet-update-ppe-backward-compatible-two-way-hash.patch
old mode 100644
new mode 100755
similarity index 96%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-1-ethernet-update-ppe-backward-compatible-two-way-hash.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-ethernet-update-ppe-backward-compatible-two-way-hash.patch
index ab5bbab..cfe29e7
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-1-ethernet-update-ppe-backward-compatible-two-way-hash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-ethernet-update-ppe-backward-compatible-two-way-hash.patch
@@ -18,49 +18,49 @@
  	.has_sram = false,
 +	.hash_way = 2,
  	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
- 		.txd_size = sizeof(struct mtk_tx_dma),
 @@ -4573,6 +4575,7 @@ static const struct mtk_soc_data mt7621_
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.hash_way = 2,
  	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
- 		.txd_size = sizeof(struct mtk_tx_dma),
 @@ -4589,6 +4592,7 @@ static const struct mtk_soc_data mt7622_
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.hash_way = 2,
  	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
- 		.txd_size = sizeof(struct mtk_tx_dma),
 @@ -4604,6 +4608,7 @@ static const struct mtk_soc_data mt7623_
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
  	.has_sram = false,
 +	.hash_way = 2,
  	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
- 		.txd_size = sizeof(struct mtk_tx_dma),
 @@ -4635,6 +4640,7 @@ static const struct mtk_soc_data mt7986_
  	.required_clks = MT7986_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = true,
 +	.hash_way = 4,
  	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
- 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 @@ -4651,6 +4657,8 @@ static const struct mtk_soc_data mt7981_
  	.required_clks = MT7981_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = true,
 +	.hash_way = 4,
 +	.offload_version = 2,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
- 		.rxd_size = sizeof(struct mtk_rx_dma_v2),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index 4a69bd0..35a7543 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-add-mtkhnat-flow-accounting.patch
old mode 100644
new mode 100755
similarity index 98%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-add-mtkhnat-flow-accounting.patch
index 5b6253f..ed90d2c
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-add-mtkhnat-flow-accounting.patch
@@ -19,7 +19,7 @@
 +	.has_accounting = false,
  	.hash_way = 2,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4073,6 +4075,7 @@ static const struct mtk_soc_data mt7621_data = {
  	.required_clks = MT7621_CLKS_BITMAP,
  	.required_pctl = false,
@@ -27,7 +27,7 @@
 +	.has_accounting = false,
  	.hash_way = 2,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4090,6 +4093,7 @@ static const struct mtk_soc_data mt7622_data = {
  	.required_clks = MT7622_CLKS_BITMAP,
  	.required_pctl = false,
@@ -35,7 +35,7 @@
 +	.has_accounting = true,
  	.hash_way = 2,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4106,6 +4110,7 @@ static const struct mtk_soc_data mt7623_data = {
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
@@ -43,15 +43,15 @@
 +	.has_accounting = false,
  	.hash_way = 2,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4123,6 +4128,7 @@ static const struct mtk_soc_data mt7629_data = {
  	.required_clks = MT7629_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.has_accounting = true,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 @@ -4138,6 +4144,7 @@ static const struct mtk_soc_data mt7986_data = {
  	.required_clks = MT7986_CLKS_BITMAP,
  	.required_pctl = false,
@@ -59,7 +59,7 @@
 +	.has_accounting = true,
  	.hash_way = 4,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4155,6 +4162,7 @@ static const struct mtk_soc_data mt7981_data = {
  	.required_clks = MT7981_CLKS_BITMAP,
  	.required_pctl = false,
@@ -67,15 +67,15 @@
 +	.has_accounting = true,
  	.hash_way = 4,
  	.offload_version = 2,
- 	.txrx = {
+	.rss_num = 0,
 @@ -4171,6 +4179,7 @@ static const struct mtk_soc_data rt5350_data = {
  	.required_clks = MT7628_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = false,
 +	.has_accounting = false,
+	.rss_num = 0,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma),
- 		.rxd_size = sizeof(struct mtk_rx_dma),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index f659633..5e16fa8 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-3-flow-offload-add-mtkhnat-qdma-qos.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-flow-offload-add-mtkhnat-qdma-qos.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-3-flow-offload-add-mtkhnat-qdma-qos.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-flow-offload-add-mtkhnat-qdma-qos.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-4-flow-offload-ovs-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-flow-offload-ovs-support.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-4-flow-offload-ovs-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-flow-offload-ovs-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-5-update-net-bridge-for-bridger.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-update-net-bridge-for-bridger.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-5-update-net-bridge-for-bridger.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-update-net-bridge-for-bridger.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-6-ethernet-update-ppe-from-mt7986-to-mt7988.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-ethernet-update-ppe-from-mt7986-to-mt7988.patch
old mode 100644
new mode 100755
similarity index 99%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-6-ethernet-update-ppe-from-mt7986-to-mt7988.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-ethernet-update-ppe-from-mt7986-to-mt7988.patch
index aac0808..d9af44d
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-6-ethernet-update-ppe-from-mt7986-to-mt7988.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-ethernet-update-ppe-from-mt7986-to-mt7988.patch
@@ -41,6 +41,7 @@
 +	.has_accounting = true,
 +	.hash_way = 4,
 +	.offload_version = 2,
+	.rss_num = 4,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
  		.rxd_size = sizeof(struct mtk_rx_dma_v2),
@@ -50,7 +51,6 @@
  		.qdma_tx_sch = 4,
  	},
  };
- 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index 5b39d87..94bd423 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-7-mediatek-ethernet-add-wifi2wifi-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-mediatek-ethernet-add-wifi2wifi-offload-support.patch
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-7-mediatek-ethernet-add-wifi2wifi-offload-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-mediatek-ethernet-add-wifi2wifi-offload-support.patch
index 85e15c9..c810ff1 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-7-mediatek-ethernet-add-wifi2wifi-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-mediatek-ethernet-add-wifi2wifi-offload-support.patch
@@ -56,7 +56,7 @@
  
  	if (!tc_can_offload(dev))
  		return -EOPNOTSUPP;
-@@ -577,17 +587,22 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_pri
+@@ -577,14 +587,19 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_pri
  	return err;
  }
  
@@ -69,7 +69,6 @@
 -	struct mtk_mac *mac = netdev_priv(dev);
 -	struct mtk_eth *eth = mac->hw;
 +	struct mtk_mac *mac;
- 	struct nf_flowtable *flowtable;
  	static LIST_HEAD(block_cb_list);
  	struct flow_block_cb *block_cb;
  	flow_setup_cb_t *cb;
@@ -80,8 +79,6 @@
 +		eth = mac->hw;
 +	}
 +
- 	flowtable = container_of(f->block, struct nf_flowtable, flow_block);
- 
  	for (i = 0; i < eth->ppe_num; i++) {
 @@ -610,7 +625,7 @@ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
  			flow_block_cb_incref(block_cb);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-8-flow-offload-add-mtkhnat-dscp.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-flow-offload-add-mtkhnat-dscp.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-8-flow-offload-add-mtkhnat-dscp.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-flow-offload-add-mtkhnat-dscp.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-9-flow-offload-add-mtkhnat-netlink.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3020-flow-offload-add-mtkhnat-netlink.patch
old mode 100644
new mode 100755
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-9-flow-offload-add-mtkhnat-netlink.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3020-flow-offload-add-mtkhnat-netlink.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index e706419..47252dd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -243,6 +243,10 @@
 CONFIG_I2C_MT65XX=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_KFIFO_BUF=y
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_TRIGGERED_BUFFER=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
@@ -264,6 +268,7 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_MAGIC_SYSRQ_SERIAL=y
 CONFIG_MARVELL_10G_PHY=y
+CONFIG_MARVELL_PHY=y
 CONFIG_MAXLINEAR_GPHY=y
 CONFIG_MD=y
 CONFIG_MDIO_BUS=y
@@ -409,6 +414,9 @@
 CONFIG_RCU_NEED_SEGCBLIST=y
 CONFIG_RCU_STALL_COMMON=y
 CONFIG_REALTEK_PHY=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_REED_SOLOMON_ENC8=y
 CONFIG_REGMAP=y
 CONFIG_REGMAP_I2C=y
 CONFIG_REGMAP_MMIO=y
@@ -418,6 +426,7 @@
 CONFIG_REGULATOR_RT5190A=y
 CONFIG_RESET_CONTROLLER=y
 CONFIG_RFS_ACCEL=y
+CONFIG_RICHTEK_RTQ6056=y
 CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
 CONFIG_RPS=y
 CONFIG_RTC_CLASS=y
@@ -504,6 +513,3 @@
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZONE_DMA32=y
-# CONFIG_BPF_KPROBE_OVERRIDE is not set
-# CONFIG_HIST_TRIGGERS is not set
-# CONFIG_FUNCTION_ERROR_INJECTION is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/1002-mtkhnat-add-support-for-virtual-interface-acceleration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2708-mtkhnat-add-support-for-virtual-interface-acceleration.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/1002-mtkhnat-add-support-for-virtual-interface-acceleration.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2708-mtkhnat-add-support-for-virtual-interface-acceleration.patch
index 150087a..4d21ebd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/1002-mtkhnat-add-support-for-virtual-interface-acceleration.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2708-mtkhnat-add-support-for-virtual-interface-acceleration.patch
@@ -1,8 +1,21 @@
+From fd6e50fdeb1d943b889a5aa093790a798ae598d3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:29 +0800
+Subject: [PATCH] 
+ [networking][999-2708-mtkhnat-add-support-for-virtual-interface-acceleration.patch]
+
+---
+ include/net/netfilter/nf_flow_table.h |  3 +++
+ net/8021q/vlan_dev.c                  |  1 +
+ net/ipv6/ip6_tunnel.c                 | 24 ++++++++++++++++++++++++
+ net/ipv6/sit.c                        | 24 ++++++++++++++++++++++++
+ 4 files changed, 52 insertions(+)
+
 diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index 3d73c0c..960ade1 100644
+index 16dbf5461..4cb73a7cb 100644
 --- a/include/net/netfilter/nf_flow_table.h
 +++ b/include/net/netfilter/nf_flow_table.h
-@@ -92,9 +92,12 @@ struct flow_offload {
+@@ -94,9 +94,12 @@ struct flow_offload {
  #define FLOW_OFFLOAD_PATH_VLAN		BIT(1)
  #define FLOW_OFFLOAD_PATH_PPPOE		BIT(2)
  #define FLOW_OFFLOAD_PATH_DSA		BIT(3)
@@ -16,10 +29,10 @@
  
  	u8 eth_src[ETH_ALEN];
 diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
-index be6801524..c51af70f6 100644
+index f973bec77..dbb3cea5c 100644
 --- a/net/8021q/vlan_dev.c
 +++ b/net/8021q/vlan_dev.c
-@@ -761,6 +761,7 @@ static int vlan_dev_flow_offload_check(struct flow_offload_hw_path *path)
+@@ -764,6 +764,7 @@ static int vlan_dev_flow_offload_check(struct flow_offload_hw_path *path)
  	path->flags |= FLOW_OFFLOAD_PATH_VLAN;
  	path->vlan_proto = vlan->vlan_proto;
  	path->vlan_id = vlan->vlan_id;
@@ -28,7 +41,7 @@
  
  	if (vlan->real_dev->netdev_ops->ndo_flow_offload_check)
 diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
-index 1b7e3141c..da4e34f74 100644
+index 71ef26e60..f8302fdd5 100644
 --- a/net/ipv6/ip6_tunnel.c
 +++ b/net/ipv6/ip6_tunnel.c
 @@ -57,6 +57,11 @@
@@ -43,7 +56,7 @@
  MODULE_AUTHOR("Ville Nuorvala");
  MODULE_DESCRIPTION("IPv6 tunneling device");
  MODULE_LICENSE("GPL");
-@@ -1880,6 +1885,22 @@ int ip6_tnl_get_iflink(const struct net_device *dev)
+@@ -1889,6 +1894,22 @@ int ip6_tnl_get_iflink(const struct net_device *dev)
  }
  EXPORT_SYMBOL(ip6_tnl_get_iflink);
  
@@ -66,7 +79,7 @@
  int ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops,
  			  unsigned int num)
  {
-@@ -1941,6 +1962,9 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
+@@ -1950,6 +1971,9 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
  	.ndo_change_mtu = ip6_tnl_change_mtu,
  	.ndo_get_stats	= ip6_get_stats,
  	.ndo_get_iflink = ip6_tnl_get_iflink,
@@ -77,7 +90,7 @@
  
  #define IPXIPX_FEATURES (NETIF_F_SG |		\
 diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
-index 98954830c..42b6e8c4c 100644
+index 117960895..0844a95e3 100644
 --- a/net/ipv6/sit.c
 +++ b/net/ipv6/sit.c
 @@ -52,6 +52,11 @@
@@ -92,7 +105,7 @@
  /*
     This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
  
-@@ -1345,6 +1350,22 @@ ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+@@ -1342,6 +1347,22 @@ done:
  	return err;
  }
  
@@ -115,7 +128,7 @@
  static const struct net_device_ops ipip6_netdev_ops = {
  	.ndo_init	= ipip6_tunnel_init,
  	.ndo_uninit	= ipip6_tunnel_uninit,
-@@ -1352,6 +1373,9 @@ static const struct net_device_ops ipip6_netdev_ops = {
+@@ -1349,6 +1370,9 @@ static const struct net_device_ops ipip6_netdev_ops = {
  	.ndo_do_ioctl	= ipip6_tunnel_ioctl,
  	.ndo_get_stats64 = ip_tunnel_get_stats64,
  	.ndo_get_iflink = ip_tunnel_get_iflink,
@@ -125,3 +138,6 @@
  };
  
  static void ipip6_dev_free(struct net_device *dev)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2726-mtkhnat-tnl-interface-offload-check.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2726-mtkhnat-tnl-interface-offload-check.patch
new file mode 100644
index 0000000..e94185f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2726-mtkhnat-tnl-interface-offload-check.patch
@@ -0,0 +1,62 @@
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -96,6 +96,7 @@ struct flow_offload {
+ #define FLOW_OFFLOAD_PATH_DSA		BIT(3)
+ #define FLOW_OFFLOAD_PATH_DSLITE	BIT(4)
+ #define FLOW_OFFLOAD_PATH_6RD		BIT(5)
++#define FLOW_OFFLOAD_PATH_TNL		BIT(6)
+ 
+ struct flow_offload_hw_path {
+ 	struct net_device *dev;
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -89,6 +89,7 @@
+ #include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
++#include <net/netfilter/nf_flow_table.h>
+ #include <net/ip.h>
+ #include <net/udp.h>
+ #include <net/inet_common.h>
+@@ -124,9 +125,14 @@ struct pppol2tp_session {
+ };
+ 
+ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
++static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan,
++				       struct flow_offload_hw_path *path);
+ 
+ static const struct ppp_channel_ops pppol2tp_chan_ops = {
+ 	.start_xmit =  pppol2tp_xmit,
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++	.flow_offload_check = l2tp_ppp_flow_offload_check,
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
+ };
+ 
+ static const struct proto_ops pppol2tp_ops;
+@@ -335,6 +341,26 @@ error:
+ 	return error;
+ }
+ 
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan,
++				       struct flow_offload_hw_path *path)
++{
++	struct sock *sk = (struct sock *)chan->private;
++	struct l2tp_session *session;
++
++	if (path->flags & FLOW_OFFLOAD_PATH_TNL)
++		return -EEXIST;
++
++	session = pppol2tp_sock_to_session(sk);
++	if (!session)
++		return -EINVAL;
++
++	path->flags |= FLOW_OFFLOAD_PATH_TNL;
++
++	return 0;
++}
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
++
+ /* Transmit function called by generic PPP driver.  Sends PPP frame
+  * over PPPoL2TP socket.
+  *
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
deleted file mode 100644
index fdf953d..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
-index 927ebc5..03bb7b5 100644
---- a/drivers/cpufreq/mediatek-cpufreq.c
-+++ b/drivers/cpufreq/mediatek-cpufreq.c
-@@ -573,6 +573,7 @@ static int __init mtk_cpufreq_driver_init(void)
- 	pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
- 	if (IS_ERR(pdev)) {
- 		pr_err("failed to register mtk-cpufreq platform device\n");
-+		platform_driver_unregister(&mtk_cpufreq_platdrv);
- 		return PTR_ERR(pdev);
- 	}
- 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
deleted file mode 100644
index 7fc4f1d..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
+++ /dev/null
@@ -1,9 +0,0 @@
-diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
-index b017330..1c485e3 100644
---- a/drivers/soc/mediatek/Makefile
-+++ b/drivers/soc/mediatek/Makefile
-@@ -3,3 +3,4 @@ obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
- obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
- obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
- obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
-+obj-$(CONFIG_MTK_SCPSYS) += mtk-pm-domains.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0020-dts-mt7622-enable-new-mtk-snand-for-ubi.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0020-dts-mt7622-enable-new-mtk-snand-for-ubi.patch
deleted file mode 100644
index 3a9e061..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0020-dts-mt7622-enable-new-mtk-snand-for-ubi.patch
+++ /dev/null
@@ -1,23 +0,0 @@
---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
-@@ -567,6 +567,20 @@
- 		status = "disabled";
- 	};
- 
-+	snand: snfi@1100d000 {
-+		compatible = "mediatek,mt7622-snand";
-+		reg = <0 0x1100d000 0 0x1000>, <0 0x1100e000 0 0x1000>;
-+		reg-names = "nfi", "ecc";
-+		interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
-+		clocks = <&pericfg CLK_PERI_NFI_PD>,
-+			 <&pericfg CLK_PERI_SNFI_PD>,
-+			 <&pericfg CLK_PERI_NFIECC_PD>;
-+		clock-names = "nfi_clk", "pad_clk", "ecc_clk";
-+		#address-cells = <1>;
-+		#size-cells = <0>;
-+		status = "disabled";
-+	};
-+
- 	nor_flash: spi@11014000 {
- 		compatible = "mediatek,mt7622-nor",
- 			     "mediatek,mt8173-nor";
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0021-dts-mt7622-remove-cooling-device.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0021-dts-mt7622-remove-cooling-device.patch
deleted file mode 100644
index efcc14f..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0021-dts-mt7622-remove-cooling-device.patch
+++ /dev/null
@@ -1,31 +0,0 @@
---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
-@@ -167,25 +167,6 @@
- 				};
- 			};
- 
--			cooling-maps {
--				map0 {
--					trip = <&cpu_passive>;
--					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
--							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
--				};
--
--				map1 {
--					trip = <&cpu_active>;
--					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
--							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
--				};
--
--				map2 {
--					trip = <&cpu_hot>;
--					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
--							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
--				};
--			};
- 		};
- 	};
- 
--- 
-2.29.2
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0200-show_model_name_in_cpuinfo_on_arm64.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0200-show_model_name_in_cpuinfo_on_arm64.patch
deleted file mode 100644
index 98e5ab6..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0200-show_model_name_in_cpuinfo_on_arm64.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: linux-5.4.70/arch/arm64/kernel/cpuinfo.c
-===================================================================
---- linux-5.4.70.orig/arch/arm64/kernel/cpuinfo.c
-+++ linux-5.4.70/arch/arm64/kernel/cpuinfo.c
-@@ -139,9 +139,8 @@ static int c_show(struct seq_file *m, vo
- 		 * "processor".  Give glibc what it expects.
- 		 */
- 		seq_printf(m, "processor\t: %d\n", i);
--		if (compat)
--			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
--				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
-+		seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
-+			   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
- 
- 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
- 			   loops_per_jiffy / (500000UL/HZ),
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0491-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0491-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
deleted file mode 100644
index 7951d63..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0491-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -86,7 +86,7 @@ static int mx35lf1ge4ab_ecc_get_status(s
- 		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
- 			return nand->eccreq.strength;
- 
--		if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr))
-+		if (eccsr > nand->eccreq.strength || !eccsr)
- 			return nand->eccreq.strength;
- 
- 		return eccsr;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0504-macsec-revert-async-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0504-macsec-revert-async-support.patch
deleted file mode 100644
index d52db50..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0504-macsec-revert-async-support.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/net/macsec.c
-+++ b/drivers/net/macsec.c
-@@ -1309,8 +1309,7 @@
- 	struct crypto_aead *tfm;
- 	int ret;
- 
--	/* Pick a sync gcm(aes) cipher to ensure order is preserved. */
--	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
-+	tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
- 
- 	if (IS_ERR(tfm))
- 		return tfm;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-spi-mtk-nor-fix-timeout-calculation-overflow.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-spi-mtk-nor-fix-timeout-calculation-overflow.patch
deleted file mode 100644
index 86b2089..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-spi-mtk-nor-fix-timeout-calculation-overflow.patch
+++ /dev/null
@@ -1,179 +0,0 @@
-From patchwork Tue Sep 22 11:49:02 2020
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Chuanhong Guo <gch981213@gmail.com>
-X-Patchwork-Id: 11792387
-Return-Path: 
- <SRS0=i66O=C7=lists.infradead.org=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@kernel.org>
-Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
- [172.30.200.123])
-	by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 21EB0618
-	for <patchwork-linux-arm@patchwork.kernel.org>;
- Tue, 22 Sep 2020 11:51:33 +0000 (UTC)
-Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134])
-	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
-	(No client certificate requested)
-	by mail.kernel.org (Postfix) with ESMTPS id E15FF221EB
-	for <patchwork-linux-arm@patchwork.kernel.org>;
- Tue, 22 Sep 2020 11:51:32 +0000 (UTC)
-Authentication-Results: mail.kernel.org;
-	dkim=pass (2048-bit key) header.d=lists.infradead.org
- header.i=@lists.infradead.org header.b="KBg/skkC";
-	dkim=fail reason="signature verification failed" (2048-bit key)
- header.d=gmail.com header.i=@gmail.com header.b="Gtqp4rrT"
-DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E15FF221EB
-Authentication-Results: mail.kernel.org;
- dmarc=fail (p=none dis=none) header.from=gmail.com
-Authentication-Results: mail.kernel.org;
- spf=none
- smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
-	d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding:
-	Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive:
-	List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To:From:
-	Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender
-	:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner;
-	bh=Xg61WV47qNPjINdHDPnF6T3q8GN8f9evwhTMdYR0Zqs=; b=KBg/skkCvnF7/8AlleTay0p/H2
-	hC4Lzo+slWhX5/eepUEXzhTr5ORf4Dx9gD65UEuordKQKFpg6Y9ApoGaYtmBJ0vABdAZt+oVG4sFf
-	K3z3CYV6EZ5qvwsZt53Xm3YsHojgu+Lnc/MGgGWBRjCtTP7gshm480pZ0w6ADgHvrym5hNajUF6+5
-	zMm5Wwq34jxUApGU7k5FAPsvO5ctYCuhECq/mLB6tplCVh3/+XLdSiHMUlY17fh+xs732kgaDotuQ
-	QYgXtDmMB1pVKCq5cf3Bcuz7Ww47vLSx4rBxtdB/vpp2w9SdrU6K8Q7DuJ3+XrGfbMhKtBU5ektA8
-	GxEUUaKw==;
-Received: from localhost ([::1] helo=merlin.infradead.org)
-	by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
-	id 1kKgo2-0000Ze-Fb; Tue, 22 Sep 2020 11:50:00 +0000
-Received: from mail-pg1-x543.google.com ([2607:f8b0:4864:20::543])
- by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
- id 1kKgnr-0000Vv-6z; Tue, 22 Sep 2020 11:49:49 +0000
-Received: by mail-pg1-x543.google.com with SMTP id o25so6798387pgm.0;
- Tue, 22 Sep 2020 04:49:46 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
- h=from:to:cc:subject:date:message-id:mime-version
- :content-transfer-encoding;
- bh=EJwpKrbgqo/Jc/SWHvyAGB9CrpkZ5L1Hzq9tInFHTYk=;
- b=Gtqp4rrTgM1+bYxfUQXe+lfPcgHRW6GccdN42Iszl6ozMbezvftl1BUcKE22S6eFW3
- Vs+lcKZN9Eh9C53YAAd0cuZYhJ2GqlfGNLA/9SyB7s/gIwHqO9Cuu17YpB9dAFfEUxoS
- 825uUcTeRe6BTagZAh2/MBluiMY3TszRi94MbOftxUg+wSqp0wMAPe9RN0gAEc/l2xgK
- 8PhXbZv3uItI4QqoKYiz93vrF/zYhj+oGTI44g2li2fpAgCNL7lXCpSE2C9NsEe+YqTw
- aO5A3W8t4jvp8oCJEvr/MWY1ZZLd1fVJ17W3aGXoDi/7EUcAvX9G5Ee7U68UXGMtty/d
- z5Nw==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=1e100.net; s=20161025;
- h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version
- :content-transfer-encoding;
- bh=EJwpKrbgqo/Jc/SWHvyAGB9CrpkZ5L1Hzq9tInFHTYk=;
- b=XhcpP16zYyJr/qCT9JbO3fn8RyfI44xJL3hvgNrlcr4ljkEZ4TF6OfyhjdEZYeeA3C
- kLlWuAqrSn6mweuhS2LZ0BV5QL/YYaVO4wP4B/y3j+tNbnW3JNM0NtEY19pOtaM4vYK/
- tPuNxld5RvJWxQ9BLs8hH6y7j/ob6oDug170P5YkwK6Wa/FLCi2bw92/vldhdnFP/Nny
- 1bbiWRVls1Ra/Q3z90tGViMkBdlcff6MI9DR5M6a1HTQN7kN9rLDCMGs3r9XVComY07N
- ECbrZbL+iJwuRuT43RAUxE72X/Pn0WYD20unzITf8bta92usNDRgEuxc1bLyL+uHxgUk
- YQKA==
-X-Gm-Message-State: AOAM531Xr1Bg4uwupCAPpH4eBWVrXGALjIWa+5AVNZ8w6ltS4BGgWv6b
- e4g6ycKnUp/KalpJhOMi90o=
-X-Google-Smtp-Source: 
- ABdhPJx36OliaaLkiX3ZeZNNWgd/qSKiRor2X0eeHScDrjMSi5bTiEzAfX5j7hkQgqz8ZUT0qqLRNA==
-X-Received: by 2002:a63:1863:: with SMTP id 35mr3131307pgy.413.1600775385014;
- Tue, 22 Sep 2020 04:49:45 -0700 (PDT)
-Received: from guoguo-omen.lan ([156.96.148.94])
- by smtp.gmail.com with ESMTPSA id r4sm2223750pjf.4.2020.09.22.04.49.42
- (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
- Tue, 22 Sep 2020 04:49:44 -0700 (PDT)
-From: Chuanhong Guo <gch981213@gmail.com>
-To: linux-spi@vger.kernel.org
-Subject: [PATCH v2] spi: spi-mtk-nor: fix timeout calculation overflow
-Date: Tue, 22 Sep 2020 19:49:02 +0800
-Message-Id: <20200922114905.2942859-1-gch981213@gmail.com>
-X-Mailer: git-send-email 2.26.2
-MIME-Version: 1.0
-X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 
-X-CRM114-CacheID: sfid-20200922_074948_345420_69207EBE 
-X-CRM114-Status: GOOD (  12.60  )
-X-Spam-Score: 2.6 (++)
-X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary:
- Content analysis details:   (2.6 points)
- pts rule name              description
- ---- ----------------------
- --------------------------------------------------
- 2.6 RCVD_IN_SBL            RBL: Received via a relay in Spamhaus SBL
- [156.96.148.94 listed in zen.spamhaus.org]
- -0.0 RCVD_IN_DNSWL_NONE     RBL: Sender listed at https://www.dnswl.org/,
- no trust [2607:f8b0:4864:20:0:0:0:543 listed in]
- [list.dnswl.org]
- 0.0 FREEMAIL_FROM          Sender email is commonly abused enduser mail
- provider [gch981213[at]gmail.com]
- 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends
- in digit [gch981213[at]gmail.com]
- -0.0 SPF_PASS               SPF: sender matches SPF record
- 0.0 SPF_HELO_NONE          SPF: HELO does not publish an SPF Record
- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
- -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from
- author's domain
- -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from
- envelope-from domain
- 0.1 DKIM_SIGNED            Message has a DKIM or DK signature,
- not necessarily
- valid
-X-BeenThere: linux-arm-kernel@lists.infradead.org
-X-Mailman-Version: 2.1.29
-Precedence: list
-List-Id: <linux-arm-kernel.lists.infradead.org>
-List-Unsubscribe: 
- <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
-List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
-List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
-List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
-List-Subscribe: 
- <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
-Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
- Mark Brown <broonie@kernel.org>, linux-mediatek@lists.infradead.org,
- bayi.cheng@mediatek.com, Matthias Brugger <matthias.bgg@gmail.com>,
- Chuanhong Guo <gch981213@gmail.com>, linux-arm-kernel@lists.infradead.org
-Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
-Errors-To: 
- linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-
-CLK_TO_US macro is used to calculate potential transfer time for various
-timeout handling. However it overflows on transfer bigger than 512 bytes
-because it first did (len * 8 * 1000000).
-This controller typically operates at 45MHz. This patch did 2 things:
-1. calculate clock / 1000000 first
-2. add a 4M transfer size cap so that the final timeout in DMA reading
-   doesn't overflow
-
-Fixes: 881d1ee9fe81f ("spi: add support for mediatek spi-nor controller")
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
----
-
-Change since v1: fix transfer size cap to 4M
-
- drivers/spi/spi-mtk-nor.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
-index 6e6ca2b8e6c82..62f5ff2779884 100644
---- a/drivers/spi/spi-mtk-nor.c
-+++ b/drivers/spi/spi-mtk-nor.c
-@@ -89,7 +89,7 @@
- // Buffered page program can do one 128-byte transfer
- #define MTK_NOR_PP_SIZE			128
- 
--#define CLK_TO_US(sp, clkcnt)		((clkcnt) * 1000000 / sp->spi_freq)
-+#define CLK_TO_US(sp, clkcnt)		DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)
- 
- struct mtk_nor {
- 	struct spi_controller *ctlr;
-@@ -177,6 +177,10 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
- 	if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
- 		if ((op->data.dir == SPI_MEM_DATA_IN) &&
- 		    mtk_nor_match_read(op)) {
-+			// limit size to prevent timeout calculation overflow
-+			if (op->data.nbytes > 0x400000)
-+				op->data.nbytes = 0x400000;
-+
- 			if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) ||
- 			    (op->data.nbytes < MTK_NOR_DMA_ALIGN))
- 				op->data.nbytes = 1;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0667-spi-mediatek-fix-timeout-for-large-data.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0667-spi-mediatek-fix-timeout-for-large-data.patch
deleted file mode 100644
index a04f5d6..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0667-spi-mediatek-fix-timeout-for-large-data.patch
+++ /dev/null
@@ -1,34 +0,0 @@
---- a/drivers/spi/spi-mt65xx.c
-+++ b/drivers/spi/spi-mt65xx.c
-@@ -720,6 +720,23 @@ static irqreturn_t mtk_spi_interrupt(int
- 	return IRQ_HANDLED;
- }
- 
-+static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
-+                                      struct spi_mem_op *op)
-+{
-+	int opcode_len;
-+
-+	if(!op->data.nbytes)
-+		return 0;
-+
-+	if (op->data.dir != SPI_MEM_NO_DATA) {
-+		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
-+		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE)
-+			op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE -opcode_len;
-+	}
-+
-+	return 0;
-+}
-+
- static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
- 				     const struct spi_mem_op *op)
- {
-@@ -946,6 +963,7 @@ err_exit:
- }
- 
- static const struct spi_controller_mem_ops mtk_spi_mem_ops = {
-+	.adjust_op_size = mtk_spi_mem_adjust_op_size,
- 	.supports_op = mtk_spi_mem_supports_op,
- 	.exec_op = mtk_spi_mem_exec_op,
- };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0668-spi-mediatek-fix-dma-unmap-twice.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0668-spi-mediatek-fix-dma-unmap-twice.patch
deleted file mode 100644
index 31562bf..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0668-spi-mediatek-fix-dma-unmap-twice.patch
+++ /dev/null
@@ -1,16 +0,0 @@
---- a/drivers/spi/spi-mt65xx.c
-+++ b/drivers/spi/spi-mt65xx.c
-@@ -946,12 +946,10 @@ static int mtk_spi_mem_exec_op(struct sp
- 		reg_val &= ~SPI_CMD_RX_DMA;
- 	writel(reg_val, mdata->base + SPI_CMD_REG);
- 
-+unmap_rx_dma:
- 	if (op->data.dir == SPI_MEM_DATA_IN)
- 		dma_unmap_single(mdata->dev, mdata->rx_dma,
- 				 op->data.nbytes, DMA_FROM_DEVICE);
--unmap_rx_dma:
--	dma_unmap_single(mdata->dev, mdata->rx_dma,
--			 op->data.nbytes, DMA_FROM_DEVICE);
- unmap_tx_dma:
- 	dma_unmap_single(mdata->dev, mdata->tx_dma,
- 			 tx_size, DMA_TO_DEVICE);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0669-fix-SPIM-NAND-and-NOR-probing.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0669-fix-SPIM-NAND-and-NOR-probing.patch
deleted file mode 100644
index 582771b..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0669-fix-SPIM-NAND-and-NOR-probing.patch
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/drivers/spi/spi-mt65xx.c
-+++ b/drivers/spi/spi-mt65xx.c
-@@ -1073,7 +1073,7 @@ static int mtk_spi_probe(struct platform
- 		goto err_put_master;
- 	}
- 
--/*
-+
- 	mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk");
- 	if (IS_ERR(mdata->parent_clk)) {
- 		ret = PTR_ERR(mdata->parent_clk);
-@@ -1101,17 +1101,17 @@ static int mtk_spi_probe(struct platform
- 		goto err_put_master;
- 	}
- 
--	ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk);
-+	/*ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk);
- 	if (ret < 0) {
- 		dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret);
- 		clk_disable_unprepare(mdata->spi_clk);
- 		goto err_put_master;
- 	}
- 
--	clk_disable_unprepare(mdata->spi_clk);
-+	clk_disable_unprepare(mdata->sel_clk);*/
-+
-+	//pm_runtime_enable(&pdev->dev);
- 
--	pm_runtime_enable(&pdev->dev);
--*/
- 	ret = devm_spi_register_master(&pdev->dev, master);
- 	if (ret) {
- 		dev_err(&pdev->dev, "failed to register master (%d)\n", ret);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0701-fix-mtk-nfi-driver-dependency.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0701-fix-mtk-nfi-driver-dependency.patch
deleted file mode 100644
index 3023076..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0701-fix-mtk-nfi-driver-dependency.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -429,6 +429,7 @@ config SPI_MT65XX
- 
- config SPI_MTK_SNFI
- 	tristate "MediaTek SPI NAND interface"
-+	depends on MTD
- 	select MTD_SPI_NAND
- 	help
- 	  This selects the SPI NAND FLASH interface(SNFI),
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0920-kernel-MT7988-fix-spi-dma-unmap.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0920-kernel-MT7988-fix-spi-dma-unmap.patch
deleted file mode 100644
index 5129e37..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0920-kernel-MT7988-fix-spi-dma-unmap.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 38d0cd2179791e27f06e1cfc6773f35b699ee99a Mon Sep 17 00:00:00 2001
-From: liya Li <ot_liya.li@mediatek.com>
-Date: Thu, 2 Feb 2023 14:26:39 +0800
-Subject: [PATCH] [WCNCR00293802][kernel][MT7988] fix spi dma unmap
-
-[Description]
-Use dma_unmap_single before memcpy to ensure that
-CPU can get the latest and correct data
-
-[Release-log]
-N/A
-
-Signed-off-by: liya Li <ot_liya.li@mediatek.com>
-Change-Id: Ib0b51e34e289c670f0d020fb62a15078ed116203
----
- drivers/spi/spi-mt65xx.c                    | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index 1b272d15cc..2034d19790 100644
---- a/drivers/spi/spi-mt65xx.c
-+++ b/drivers/spi/spi-mt65xx.c
-@@ -978,12 +978,12 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
- 
- unmap_rx_dma:
- 	if (op->data.dir == SPI_MEM_DATA_IN) {
-+		dma_unmap_single(mdata->dev, mdata->rx_dma,
-+				 op->data.nbytes, DMA_FROM_DEVICE);
- 		if(!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
- 			memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes);
- 			kfree(rx_tmp_buf);
- 		}
--		dma_unmap_single(mdata->dev, mdata->rx_dma,
--				 op->data.nbytes, DMA_FROM_DEVICE);
- 	}
- unmap_tx_dma:
- 	dma_unmap_single(mdata->dev, mdata->tx_dma,
--- 
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0961-dual-image-mount-rootfs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0961-dual-image-mount-rootfs.patch
deleted file mode 100755
index 99f72c0..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0961-dual-image-mount-rootfs.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-Index: linux-5.4.224/init/do_mounts.c
-===================================================================
---- linux-5.4.224.orig/init/do_mounts.c
-+++ linux-5.4.224/init/do_mounts.c
-@@ -576,7 +576,8 @@ void __init mount_root(void)
- 	}
- #endif
- #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
--	if (!mount_ubi_rootfs())
-+	extern bool dual_boot;
-+	if (!dual_boot && !mount_ubi_rootfs())
- 		return;
- #endif
- #ifdef CONFIG_BLOCK
-Index: linux-5.4.224/kernel/boot_param.c
-===================================================================
---- linux-5.4.224.orig/kernel/boot_param.c
-+++ linux-5.4.224/kernel/boot_param.c
-@@ -10,7 +10,7 @@
- 
- #define BOOT_PARAM_STR_MAX_LEN			256
- 
--static bool dual_boot;
-+bool dual_boot;
- module_param(dual_boot, bool, 0444);
- 
- static bool no_split_rootfs_data;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/2000-misc-add-mtk-platform.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/2000-misc-add-mtk-platform.patch
deleted file mode 100644
index f280e10..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/2000-misc-add-mtk-platform.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff -urN a/drivers/misc/Kconfig b/drivers/misc/Kconfig
---- a/drivers/misc/Kconfig	2021-06-29 15:10:00.970788831 +0800
-+++ b/drivers/misc/Kconfig	2021-06-29 15:09:41.579158152 +0800
-@@ -481,4 +481,5 @@
- source "drivers/misc/ocxl/Kconfig"
- source "drivers/misc/cardreader/Kconfig"
- source "drivers/misc/habanalabs/Kconfig"
-+source "drivers/misc/mediatek/Kconfig"
- endmenu
-diff -urN a/drivers/misc/Makefile b/drivers/misc/Makefile
---- a/drivers/misc/Makefile	2021-06-29 15:10:15.150518461 +0800
-+++ b/drivers/misc/Makefile	2021-06-29 15:09:46.939056121 +0800
-@@ -57,3 +57,4 @@
- obj-$(CONFIG_PVPANIC)   	+= pvpanic.o
- obj-$(CONFIG_HABANA_AI)		+= habanalabs/
- obj-$(CONFIG_XILINX_SDFEC)	+= xilinx_sdfec.o
-+obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/400-mtd-add-mtk-snand-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/400-mtd-add-mtk-snand-driver.patch
deleted file mode 100644
index f283bd2..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/400-mtd-add-mtk-snand-driver.patch
+++ /dev/null
@@ -1,21 +0,0 @@
---- a/drivers/mtd/Kconfig
-+++ b/drivers/mtd/Kconfig
-@@ -230,6 +230,8 @@ source "drivers/mtd/hyperbus/Kconfig"
- 
- source "drivers/mtd/nmbm/Kconfig"
- 
-+source "drivers/mtd/mtk-snand/Kconfig"
-+
- source "drivers/mtd/composite/Kconfig"
- 
- endif # MTD
---- a/drivers/mtd/Makefile
-+++ b/drivers/mtd/Makefile
-@@ -35,5 +35,7 @@ obj-$(CONFIG_MTD_HYPERBUS)	+= hyperbus/
- 
- obj-y				+= nmbm/
- 
-+obj-$(CONFIG_MTK_SPI_NAND)	+= mtk-snand/
-+
- # Composite drivers must be loaded last
- obj-y				+= composite/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/415-mtd-spinand-fix-F50L1G41LB-ecc-check.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/415-mtd-spinand-fix-F50L1G41LB-ecc-check.patch
deleted file mode 100644
index e4e51bb..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/415-mtd-spinand-fix-F50L1G41LB-ecc-check.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/mtd/nand/spi/gigadevice.c
-+++ b/drivers/mtd/nand/spi/gigadevice.c
-@@ -263,8 +263,7 @@ static const struct spinand_info gigadev
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
--				     gd5fxgq4xa_ecc_get_status)),
-+		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, NULL)),
- 	SPINAND_INFO("GD5F1GQ4xA",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/416-mtd-spinor-support-EN25QX128A.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/416-mtd-spinor-support-EN25QX128A.patch
deleted file mode 100644
index 2985532..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/416-mtd-spinor-support-EN25QX128A.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/mtd/spi-nor/spi-nor.c	2022-12-14 15:29:28.587567592 +0800
-+++ b/drivers/mtd/spi-nor/spi-nor.c	2022-12-14 15:04:52.625250000 +0800
-@@ -2246,6 +2246,9 @@ static const struct flash_info spi_nor_i
- 	{ "en25qh64",   INFO(0x1c7017, 0, 64 * 1024,  128,
- 			SECT_4K | SPI_NOR_DUAL_READ) },
- 	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
-+	{ "en25qx128",	INFO(0x1c7118, 0, 64 * 1024,  256,
-+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-+			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
- 	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
- 	{ "en25s64",	INFO(0x1c3817, 0, 64 * 1024,  128, SECT_4K) },
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/492-mtd-tests-fix-pagetest-load.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/492-mtd-tests-fix-pagetest-load.patch
deleted file mode 100644
index f10b5c5..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/492-mtd-tests-fix-pagetest-load.patch
+++ /dev/null
@@ -1,42 +0,0 @@
---- a/drivers/mtd/tests/pagetest.c	2022-11-28 16:08:26.978090509 +0800
-+++ b/drivers/mtd/tests/pagetest.c	2022-11-28 16:10:04.351026850 +0800
-@@ -25,6 +25,10 @@ static int dev = -EINVAL;
- module_param(dev, int, S_IRUGO);
- MODULE_PARM_DESC(dev, "MTD device number to use");
- 
-+static int count = 10000;
-+module_param(count, int, 0444);
-+MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
-+
- static struct mtd_info *mtd;
- static unsigned char *twopages;
- static unsigned char *writebuf;
-@@ -331,7 +335,7 @@ static int __init mtd_pagetest_init(void
- 		return -EINVAL;
- 	}
- 
--	pr_info("MTD device: %d\n", dev);
-+	pr_info("MTD device: %d count:%d\n", dev, count);
- 
- 	mtd = get_mtd_device(NULL, dev);
- 	if (IS_ERR(mtd)) {
-@@ -376,6 +380,7 @@ static int __init mtd_pagetest_init(void
- 	if (err)
- 		goto out;
- 
-+LOOP:
- 	/* Erase all eraseblocks */
- 	pr_info("erasing whole device\n");
- 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
-@@ -435,7 +440,10 @@ static int __init mtd_pagetest_init(void
- 	if (err)
- 		goto out;
- 
--	pr_info("finished with %d errors\n", errcnt);
-+	pr_info("finished with %d errors count:%d\n", errcnt, count);
-+	
-+	if (count-- > 0)
-+		goto LOOP;
- out:
- 
- 	kfree(bbt);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7000-fix-race-inside-napi-enable.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7000-fix-race-inside-napi-enable.patch
deleted file mode 100644
index 052f40c..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7000-fix-race-inside-napi-enable.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From git@z Thu Jan  1 00:00:00 1970
-Subject: [PATCH v2] napi: fix race inside napi_enable
-From: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
-Date: Sat, 18 Sep 2021 16:52:32 +0800
-Message-Id: <20210918085232.71436-1-xuanzhuo@linux.alibaba.com>
-To: netdev@vger.kernel.org, linyunsheng@huawei.com
-Cc: "David S. Miller" <davem@davemloft.net>, Jakub Kicinski <kuba@kernel.org>, Eric Dumazet <edumazet@google.com>, Daniel Borkmann <daniel@iogearbox.net>, Antoine Tenart <atenart@kernel.org>, Alexander Lobakin <alobakin@pm.me>, Wei Wang <weiwan@google.com>, Taehee Yoo <ap420073@gmail.com>,Björn Töpel <bjorn@kernel.org>, Arnd Bergmann <arnd@arndb.de>, Kumar Kartikeya Dwivedi <memxor@gmail.com>, Neil Horman <nhorman@redhat.com>, Dust Li <dust.li@linux.alibaba.com>
-List-Id: <netdev.vger.kernel.org>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 7bit
-
-The process will cause napi.state to contain NAPI_STATE_SCHED and
-not in the poll_list, which will cause napi_disable() to get stuck.
-
-The prefix "NAPI_STATE_" is removed in the figure below, and
-NAPI_STATE_HASHED is ignored in napi.state.
-
-                      CPU0       |                   CPU1       | napi.state
-===============================================================================
-napi_disable()                   |                              | SCHED | NPSVC
-napi_enable()                    |                              |
-{                                |                              |
-    smp_mb__before_atomic();     |                              |
-    clear_bit(SCHED, &n->state); |                              | NPSVC
-                                 | napi_schedule_prep()         | SCHED | NPSVC
-                                 | napi_poll()                  |
-                                 |   napi_complete_done()       |
-                                 |   {                          |
-                                 |      if (n->state & (NPSVC | | (1)
-                                 |               _BUSY_POLL)))  |
-                                 |           return false;      |
-                                 |     ................         |
-                                 |   }                          | SCHED | NPSVC
-                                 |                              |
-    clear_bit(NPSVC, &n->state); |                              | SCHED
-}                                |                              |
-                                 |                              |
-napi_schedule_prep()             |                              | SCHED | MISSED (2)
-
-(1) Here return direct. Because of NAPI_STATE_NPSVC exists.
-(2) NAPI_STATE_SCHED exists. So not add napi.poll_list to sd->poll_list
-
-Since NAPI_STATE_SCHED already exists and napi is not in the
-sd->poll_list queue, NAPI_STATE_SCHED cannot be cleared and will always
-exist.
-
-1. This will cause this queue to no longer receive packets.
-2. If you encounter napi_disable under the protection of rtnl_lock, it
-   will cause the entire rtnl_lock to be locked, affecting the overall
-   system.
-
-This patch uses cmpxchg to implement napi_enable(), which ensures that
-there will be no race due to the separation of clear two bits.
-
-Fixes: 2d8bff12699abc ("netpoll: Close race condition between poll_one_napi and napi_disable")
-Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
-Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
----
- net/core/dev.c | 16 ++++++++++------
- 1 file changed, 10 insertions(+), 6 deletions(-)
-
-diff --git a/net/core/dev.c b/net/core/dev.c
-index 74fd402d26dd..7ee9fecd3aff 100644
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -6923,12 +6923,16 @@ EXPORT_SYMBOL(napi_disable);
-  */
- void napi_enable(struct napi_struct *n)
- {
--	BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
--	smp_mb__before_atomic();
--	clear_bit(NAPI_STATE_SCHED, &n->state);
--	clear_bit(NAPI_STATE_NPSVC, &n->state);
--	if (n->dev->threaded && n->thread)
--		set_bit(NAPI_STATE_THREADED, &n->state);
-+	unsigned long val, new;
-+
-+	do {
-+		val = READ_ONCE(n->state);
-+		BUG_ON(!test_bit(NAPI_STATE_SCHED, &val));
-+
-+		new = val & ~(NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC);
-+		if (n->dev->threaded && n->thread)
-+			new |= NAPIF_STATE_THREADED;
-+	} while (cmpxchg(&n->state, val, new) != val);
- }
- EXPORT_SYMBOL(napi_enable);
- 
-
--- 
-2.31.0
-
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7001-net-make-napi-disable-symmetric-with-enable.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7001-net-make-napi-disable-symmetric-with-enable.patch
deleted file mode 100644
index ac84ffc..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7001-net-make-napi-disable-symmetric-with-enable.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From git@z Thu Jan  1 00:00:00 1970
-Subject: [PATCH v2] net: make napi_disable() symmetric with enable
-From: Jakub Kicinski <kuba@kernel.org>
-Date: Fri, 24 Sep 2021 13:24:53 -0700
-Message-Id: <20210924202453.1051687-1-kuba@kernel.org>
-To: davem@davemloft.net
-Cc: netdev@vger.kernel.org, eric.dumazet@gmail.com, weiwan@google.com, xuanzhuo@linux.alibaba.com, Jakub Kicinski <kuba@kernel.org>
-List-Id: <netdev.vger.kernel.org>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 7bit
-
-Commit 3765996e4f0b ("napi: fix race inside napi_enable") fixed
-an ordering bug in napi_enable() and made the napi_enable() diverge
-from napi_disable(). The state transitions done on disable are
-not symmetric to enable.
-
-There is no known bug in napi_disable() this is just refactoring.
-
-Eric suggests we can also replace msleep(1) with a more opportunistic
-usleep_range().
-
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- net/core/dev.c | 17 ++++++++++++-----
- 1 file changed, 12 insertions(+), 5 deletions(-)
-
-diff --git a/net/core/dev.c b/net/core/dev.c
-index f24c3a9..f0a556a 100644
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -6386,18 +6386,25 @@ EXPORT_SYMBOL(netif_napi_add);
- 
- void napi_disable(struct napi_struct *n)
- {
-+	unsigned long val, new;
-+
- 	might_sleep();
- 	set_bit(NAPI_STATE_DISABLE, &n->state);
- 
--	while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
--		msleep(1);
--	while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state))
--		msleep(1);
-+	do {
-+		val = READ_ONCE(n->state);
-+		if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
-+			usleep_range(20, 200);
-+			continue;
-+		}
-+
-+		new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC;
-+		new &= ~(NAPIF_STATE_THREADED);
-+	} while (cmpxchg(&n->state, val, new) != val);
- 
- 	hrtimer_cancel(&n->timer);
- 
- 	clear_bit(NAPI_STATE_DISABLE, &n->state);
--	clear_bit(NAPI_STATE_THREADED, &n->state);
- }
- EXPORT_SYMBOL(napi_disable);
- 
--- 
-2.31.1
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7002-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7002-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch
deleted file mode 100644
index 0daf233..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/7002-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch
+++ /dev/null
@@ -1,114 +0,0 @@
-From git@z Thu Jan  1 00:00:00 1970
-Subject: [PATCH v2] net: fix premature exit from NAPI state polling in napi_disable()
-From: Alexander Lobakin <alexandr.lobakin@intel.com>
-Date: Wed, 10 Nov 2021 20:56:05 +0100
-Message-Id: <20211110195605.1304-1-alexandr.lobakin@intel.com>
-To: "David S. Miller" <davem@davemloft.net>, Jakub Kicinski <kuba@kernel.org>
-Cc: Alexander Lobakin <alexandr.lobakin@intel.com>, Jesse Brandeburg <jesse.brandeburg@intel.com>, Maciej Fijalkowski <maciej.fijalkowski@intel.com>, Michal Swiatkowski <michal.swiatkowski@intel.com>, Xuan Zhuo <xuanzhuo@linux.alibaba.com>, Antoine Tenart <atenart@kernel.org>, Eric Dumazet <edumazet@google.com>, Wei Wang <weiwan@google.com>,Björn Töpel <bjorn@kernel.org>, netdev@vger.kernel.org, linux-kernel@vger.kernel.org
-List-Id: <linux-kernel.vger.kernel.org>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 7bit
-
-Commit 719c57197010 ("net: make napi_disable() symmetric with
-enable") accidentally introduced a bug sometimes leading to a kernel
-BUG when bringing an iface up/down under heavy traffic load.
-
-Prior to this commit, napi_disable() was polling n->state until
-none of (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC) is set and then
-always flip them. Now there's a possibility to get away with the
-NAPIF_STATE_SCHE unset as 'continue' drops us to the cmpxchg()
-call with an unitialized variable, rather than straight to
-another round of the state check.
-
-Error path looks like:
-
-napi_disable():
-unsigned long val, new; /* new is uninitialized */
-
-do {
-	val = READ_ONCE(n->state); /* NAPIF_STATE_NPSVC and/or
-				      NAPIF_STATE_SCHED is set */
-	if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) { /* true */
-		usleep_range(20, 200);
-		continue; /* go straight to the condition check */
-	}
-	new = val | <...>
-} while (cmpxchg(&n->state, val, new) != val); /* state == val, cmpxchg()
-						  writes garbage */
-
-napi_enable():
-do {
-	val = READ_ONCE(n->state);
-	BUG_ON(!test_bit(NAPI_STATE_SCHED, &val)); /* 50/50 boom */
-<...>
-
-while the typical BUG splat is like:
-
-[  172.652461] ------------[ cut here ]------------
-[  172.652462] kernel BUG at net/core/dev.c:6937!
-[  172.656914] invalid opcode: 0000 [#1] PREEMPT SMP PTI
-[  172.661966] CPU: 36 PID: 2829 Comm: xdp_redirect_cp Tainted: G          I       5.15.0 #42
-[  172.670222] Hardware name: Intel Corporation S2600WFT/S2600WFT, BIOS SE5C620.86B.02.01.0014.082620210524 08/26/2021
-[  172.680646] RIP: 0010:napi_enable+0x5a/0xd0
-[  172.684832] Code: 07 49 81 cc 00 01 00 00 4c 89 e2 48 89 d8 80 e6 fb f0 48 0f b1 55 10 48 39 c3 74 10 48 8b 5d 10 f6 c7 04 75 3d f6 c3 01 75 b4 <0f> 0b 5b 5d 41 5c c3 65 ff 05 b8 e5 61 53 48 c7 c6 c0 f3 34 ad 48
-[  172.703578] RSP: 0018:ffffa3c9497477a8 EFLAGS: 00010246
-[  172.708803] RAX: ffffa3c96615a014 RBX: 0000000000000000 RCX: ffff8a4b575301a0
-< snip >
-[  172.782403] Call Trace:
-[  172.784857]  <TASK>
-[  172.786963]  ice_up_complete+0x6f/0x210 [ice]
-[  172.791349]  ice_xdp+0x136/0x320 [ice]
-[  172.795108]  ? ice_change_mtu+0x180/0x180 [ice]
-[  172.799648]  dev_xdp_install+0x61/0xe0
-[  172.803401]  dev_xdp_attach+0x1e0/0x550
-[  172.807240]  dev_change_xdp_fd+0x1e6/0x220
-[  172.811338]  do_setlink+0xee8/0x1010
-[  172.814917]  rtnl_setlink+0xe5/0x170
-[  172.818499]  ? bpf_lsm_binder_set_context_mgr+0x10/0x10
-[  172.823732]  ? security_capable+0x36/0x50
-< snip >
-
-Fix this by replacing 'do { } while (cmpxchg())' with an "infinite"
-for-loop with an explicit break.
-
-From v1 [0]:
- - just use a for-loop to simplify both the fix and the existing
-   code (Eric).
-
-[0] https://lore.kernel.org/netdev/20211110191126.1214-1-alexandr.lobakin@intel.com
-
-Fixes: 719c57197010 ("net: make napi_disable() symmetric with enable")
-Suggested-by: Eric Dumazet <edumazet@google.com> # for-loop
-Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com>
-Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
-Reviewed-by: Eric Dumazet <edumazet@google.com>
----
- net/core/dev.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/net/core/dev.c b/net/core/dev.c
-index c8f7c15..fe2c856 100644
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -6391,7 +6391,7 @@ void napi_disable(struct napi_struct *n)
- 	might_sleep();
- 	set_bit(NAPI_STATE_DISABLE, &n->state);
- 
--	do {
-+	for ( ; ; ) {
- 		val = READ_ONCE(n->state);
- 		if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
- 			usleep_range(20, 200);
-@@ -6400,7 +6400,10 @@ void napi_disable(struct napi_struct *n)
- 
- 		new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC;
- 		new &= ~(NAPIF_STATE_THREADED);
--	} while (cmpxchg(&n->state, val, new) != val);
-+
-+		if (cmpxchg(&n->state, val, new) == val)
-+			break;
-+	}
- 
- 	hrtimer_cancel(&n->timer);
- 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/740-add-gpy211-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/740-add-gpy211-phy-support.patch
deleted file mode 100644
index 2496084..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/740-add-gpy211-phy-support.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-Index: linux-5.4.119/drivers/net/phy/Kconfig
-===================================================================
---- linux-5.4.119.orig/drivers/net/phy/Kconfig
-+++ linux-5.4.119/drivers/net/phy/Kconfig
-@@ -468,6 +468,11 @@ config FIXED_PHY
- 
- 	  Currently tested with mpc866ads and mpc8349e-mitx.
- 
-+config GPY211_PHY
-+	tristate "GPY211 PHY"
-+	---help---
-+	  Supports the Intel GPY211 PHY with rate adaption.
-+
- config ICPLUS_PHY
- 	tristate "ICPlus PHYs"
- 	---help---
-Index: linux-5.4.119/drivers/net/phy/Makefile
-===================================================================
---- linux-5.4.119.orig/drivers/net/phy/Makefile
-+++ linux-5.4.119/drivers/net/phy/Makefile
-@@ -86,6 +86,7 @@ obj-$(CONFIG_DP83TC811_PHY)	+= dp83tc811
- obj-$(CONFIG_DP83848_PHY)	+= dp83848.o
- obj-$(CONFIG_DP83867_PHY)	+= dp83867.o
- obj-$(CONFIG_FIXED_PHY)		+= fixed_phy.o
-+obj-$(CONFIG_GPY211_PHY)	+= gpy211.o
- obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
- obj-$(CONFIG_INTEL_XWAY_PHY)	+= intel-xway.o
- obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch
deleted file mode 100644
index 6de04c3..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-Index: drivers/net/phy/Kconfig
-===================================================================
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -350,6 +350,11 @@ config AIROHA_EN8801S_PHY
- 	depends on HWMON || HWMON=n
- 	select MDIO_I2C
- 
-+config AIROHA_EN8801SC_PHY
-+	tristate "Drivers for Airoha EN8801S Gigabit PHYs for MediaTek SoC."
-+	---help---
-+	  Currently supports the Airoha EN8801S PHY for MediaTek SoC.
-+
- config AIROHA_EN8811H_PHY
- 	tristate "Drivers for Airoha EN8811H 2.5G Gigabit PHY"
- 	---help---
-Index: drivers/net/phy/Makefile
-===================================================================
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -68,5 +68,6 @@ ifdef CONFIG_HWMON
- aquantia-objs			+= aquantia_hwmon.o
- endif
-+obj-$(CONFIG_AIROHA_EN8801SC_PHY)	+= en8801sc.o
- obj-$(CONFIG_AIROHA_EN8811H_PHY)	+= air_en8811h.o
- obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
- obj-$(CONFIG_AX88796B_PHY)	+= ax88796b.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
deleted file mode 100644
index 161e90f..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -431,6 +431,11 @@ config MEDIATEK_GE_SOC_PHY
- 	  present in the SoCs efuse and will dynamically calibrate VCM
- 	  (common-mode voltage) during startup.
- 
-+config MEDIATEK_2P5GE_PHY
-+	tristate "MediaTek 2.5Gb Ethernet PHYs"
-+	---help---
-+	  Supports MediaTek internal 2.5Gb Ethernet PHYs.
-+
- config MICREL_PHY
- 	tristate "Micrel PHYs"
- 	---help---
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -79,6 +79,7 @@ obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
- obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
- obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
- obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)	+= mediatek-ge-soc.o
-+obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
- obj-$(CONFIG_MESON_GXL_PHY)	+= meson-gxl.o
- obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
- obj-$(CONFIG_MICREL_PHY)	+= micrel.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8001-PATCH-2-4-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8001-PATCH-2-4-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch
deleted file mode 100644
index f83e220..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8001-PATCH-2-4-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 8a79db5e83a5d52c74e6f3c40d6f312cf899213e Mon Sep 17 00:00:00 2001
-From: Jyri Sarha <jsarha@ti.com>
-Date: Wed, 8 Jan 2020 10:30:07 +0200
-Subject: [PATCH 1/5] dt-bindings: phy: Add PHY_TYPE_DP definition
-
-Add definition for DisplayPort phy type.
-
-Signed-off-by: Jyri Sarha <jsarha@ti.com>
-Reviewed-by: Roger Quadros <rogerq@ti.com>
-Reviewed-by: Kishon Vijay Abraham I <kishon@ti.com>
-Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
----
- include/dt-bindings/phy/phy.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
-index b6a1eaf1b339..1f3f866fae7b 100644
---- a/include/dt-bindings/phy/phy.h
-+++ b/include/dt-bindings/phy/phy.h
-@@ -16,5 +16,6 @@
- #define PHY_TYPE_USB2		3
- #define PHY_TYPE_USB3		4
- #define PHY_TYPE_UFS		5
-+#define PHY_TYPE_DP		6
- 
- #endif /* _DT_BINDINGS_PHY */
--- 
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8002-PATCH-3-4-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8002-PATCH-3-4-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch
deleted file mode 100644
index 7bd1ca7..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8002-PATCH-3-4-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From c5d3cdad688ed75fb311a3a671eb30ba7106d7d3 Mon Sep 17 00:00:00 2001
-From: Dilip Kota <eswara.kota@linux.intel.com>
-Date: Tue, 19 May 2020 14:19:19 +0800
-Subject: [PATCH 2/5] dt-bindings: phy: Add PHY_TYPE_XPCS definition
-
-Add definition for Ethernet PCS phy type.
-
-Signed-off-by: Dilip Kota <eswara.kota@linux.intel.com>
-Acked-by: Rob Herring <robh@kernel.org>
-Acked-By: Vinod Koul <vkoul@kernel.org>
-Link: https://lore.kernel.org/r/6091f0d2a1046f1e3656d9e33b6cc433d5465eaf.1589868358.git.eswara.kota@linux.intel.com
-Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
----
- include/dt-bindings/phy/phy.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
-index 1f3f866fae7b..3727ef72138b 100644
---- a/include/dt-bindings/phy/phy.h
-+++ b/include/dt-bindings/phy/phy.h
-@@ -17,5 +17,6 @@
- #define PHY_TYPE_USB3		4
- #define PHY_TYPE_UFS		5
- #define PHY_TYPE_DP		6
-+#define PHY_TYPE_XPCS		7
- 
- #endif /* _DT_BINDINGS_PHY */
--- 
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8003-PATCH-4-4-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8003-PATCH-4-4-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch
deleted file mode 100644
index ef5df66..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8003-PATCH-4-4-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From cea0f76a483d1270ac6f6513964e3e75193dda48 Mon Sep 17 00:00:00 2001
-From: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
-Date: Mon, 29 Jun 2020 15:00:52 +0300
-Subject: [PATCH 3/5] dt-bindings: phy: Add DT bindings for Xilinx ZynqMP PSGTR
- PHY
-
-Add DT bindings for the Xilinx ZynqMP PHY. ZynqMP SoCs have a High Speed
-Processing System Gigabit Transceiver which provides PHY capabilities to
-USB, SATA, PCIE, Display Port and Ehernet SGMII controllers.
-
-Signed-off-by: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Link: https://lore.kernel.org/r/20200629120054.29338-2-laurent.pinchart@ideasonboard.com
-Signed-off-by: Vinod Koul <vkoul@kernel.org>
----
- include/dt-bindings/phy/phy.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
-index 3727ef72138b..36e8c241cf48 100644
---- a/include/dt-bindings/phy/phy.h
-+++ b/include/dt-bindings/phy/phy.h
-@@ -18,5 +18,6 @@
- #define PHY_TYPE_UFS		5
- #define PHY_TYPE_DP		6
- #define PHY_TYPE_XPCS		7
-+#define PHY_TYPE_SGMII		8
- 
- #endif /* _DT_BINDINGS_PHY */
--- 
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9103-drivers-spi-mt65xx-add-dts-buswidth-flow.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9103-drivers-spi-mt65xx-add-dts-buswidth-flow.patch
deleted file mode 100644
index 31ceb83..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9103-drivers-spi-mt65xx-add-dts-buswidth-flow.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/spi/spi-mt65xx.c
-+++ b/drivers/spi/spi-mt65xx.c
-@@ -1080,7 +1080,7 @@ static int mtk_spi_probe(struct platform
- 		master->flags = SPI_MASTER_MUST_TX;
- 
- 	if (mdata->dev_comp->ipm_design)
--		master->mode_bits |= SPI_LOOP;
-+		master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
- 
- 	if (mdata->dev_comp->ipm_design) {
- 		mdata->dev = dev;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-mdiobus-add-c45.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1600-mdiobus-add-c45.patch
similarity index 86%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-mdiobus-add-c45.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1600-mdiobus-add-c45.patch
index 93c00b8..acc6d2a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-mdiobus-add-c45.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1600-mdiobus-add-c45.patch
@@ -1,3 +1,12 @@
+From abf7f24a61f01977b657285d6425b1185354a29a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:05:59 +0800
+Subject: [PATCH] [backport-networking-generic][999-1600-mdiobus-add-c45.patch]
+
+---
+ include/linux/mdio.h | 49 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
 diff --git a/include/linux/mdio.h b/include/linux/mdio.h
 index 0f1f784de..006d1c1e9 100644
 --- a/include/linux/mdio.h
@@ -68,5 +77,5 @@
  int mdiobus_unregister_device(struct mdio_device *mdiodev);
  bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch
new file mode 100644
index 0000000..3212b6b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch
@@ -0,0 +1,27 @@
+From 8b45e5c6b6b419305ef893e1dfdd4c69c020958b Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:05:59 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1700-macsec-revert-async-support.patch]
+
+---
+ drivers/net/macsec.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index f729f55f6..e3f03c89c 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -1311,8 +1311,7 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len)
+ 	struct crypto_aead *tfm;
+ 	int ret;
+ 
+-	/* Pick a sync gcm(aes) cipher to ensure order is preserved. */
+-	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
++	tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ 
+ 	if (IS_ERR(tfm))
+ 		return tfm;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/741-add-default-setting-to-dsa-unused-port.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1701-add-default-setting-to-dsa-unused-port.patch
similarity index 71%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/741-add-default-setting-to-dsa-unused-port.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1701-add-default-setting-to-dsa-unused-port.patch
index 7769ebd..888a312 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/741-add-default-setting-to-dsa-unused-port.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1701-add-default-setting-to-dsa-unused-port.patch
@@ -1,8 +1,19 @@
-Index: linux-5.4.124/drivers/net/dsa/mt7530.c
-===================================================================
---- linux-5.4.124.orig/drivers/net/dsa/mt7530.c
-+++ linux-5.4.124/drivers/net/dsa/mt7530.c
-@@ -1021,6 +1021,9 @@ mt7530_stp_state_set(struct dsa_switch *
+From e3dd6804fa642a733b7a6932d60bb83b6363555c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:05:59 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1701-add-default-setting-to-dsa-unused-port.patch]
+
+---
+ drivers/net/dsa/mt7530.c | 62 ++++++++++++++++++++++++++++++++++++++--
+ drivers/net/dsa/mt7530.h |  1 +
+ 2 files changed, 60 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 8ce3d51e8..008432d5c 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1022,6 +1022,9 @@ mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state)
  	struct mt7530_priv *priv = ds->priv;
  	u32 stp_state;
  
@@ -12,10 +23,11 @@
  	switch (state) {
  	case BR_STATE_DISABLED:
  		stp_state = MT7530_STP_DISABLED;
-@@ -1676,10 +1679,58 @@ mt7530_setup(struct dsa_switch *ds)
+@@ -1674,11 +1677,59 @@ mt7530_setup(struct dsa_switch *ds)
+ 	return 0;
  }
  
- static int
++static int
 +setup_unused_ports(struct dsa_switch *ds, u32 pm)
 +{
 +	struct mt7530_priv *priv = ds->priv;
@@ -62,7 +74,7 @@
 +	return 0;
 +}
 +
-+static int
+ static int
  mt7531_setup(struct dsa_switch *ds)
  {
  	struct mt7530_priv *priv = ds->priv;
@@ -71,7 +83,7 @@
  	u32 val, id;
  	int ret, i;
  
-@@ -1767,7 +1818,9 @@ mt7531_setup(struct dsa_switch *ds)
+@@ -1766,7 +1817,9 @@ mt7531_setup(struct dsa_switch *ds)
  
  		mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
  
@@ -82,7 +94,7 @@
  			mt753x_cpu_port_enable(ds, i);
  		else
  			mt7530_port_disable(ds, i);
-@@ -1777,6 +1830,9 @@ mt7531_setup(struct dsa_switch *ds)
+@@ -1776,6 +1829,9 @@ mt7531_setup(struct dsa_switch *ds)
  			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
  	}
  
@@ -92,7 +104,7 @@
  	ds->configure_vlan_while_not_filtering = true;
  
  	/* Flush the FDB table */
-@@ -2101,7 +2157,7 @@ mt7531_mac_config(struct dsa_switch *ds,
+@@ -2100,7 +2156,7 @@ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
  	case PHY_INTERFACE_MODE_RGMII_RXID:
  	case PHY_INTERFACE_MODE_RGMII_TXID:
  		dp = dsa_to_port(ds, port);
@@ -101,7 +113,7 @@
  		return mt7531_rgmii_setup(priv, port, interface, phydev);
  	case PHY_INTERFACE_MODE_SGMII:
  		return mt7531_sgmii_setup_mode_an(priv, port, interface);
-@@ -2641,7 +2697,7 @@ mt7530_probe(struct mdio_device *mdiodev
+@@ -2640,7 +2696,7 @@ mt7530_probe(struct mdio_device *mdiodev)
  	if (!priv)
  		return -ENOMEM;
  
@@ -110,10 +122,10 @@
  	if (!priv->ds)
  		return -ENOMEM;
  
-Index: linux-5.4.124/drivers/net/dsa/mt7530.h
-===================================================================
---- linux-5.4.124.orig/drivers/net/dsa/mt7530.h
-+++ linux-5.4.124/drivers/net/dsa/mt7530.h
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 6424bc90e..aa758b2d2 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
 @@ -10,6 +10,7 @@
  #define MT7530_CPU_PORT			6
  #define MT7530_NUM_FDB_RECORDS		2048
@@ -122,3 +134,6 @@
  
  enum mt753x_id {
  	ID_MT7530 = 0,
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
index 948bb69..bf4cef7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch
@@ -1,8 +1,38 @@
-Index: linux-5.4.124/drivers/net/dsa/mt7530.c
-===================================================================
---- linux-5.4.124.orig/drivers/net/dsa/mt7530.c
-+++ linux-5.4.124/drivers/net/dsa/mt7530.c
-@@ -1830,6 +1830,8 @@ mt7531_setup(struct dsa_switch *ds)
+From b736c4488d00e4b6e363220746c666176c12ea90 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:05:59 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch]
+
+---
+ drivers/net/dsa/Makefile     |    3 +-
+ drivers/net/dsa/mt7530.c     |    2 +
+ drivers/net/dsa/mt7530.h     |    1 +
+ drivers/net/dsa/mt7531_phy.c | 1378 ++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/mt7531_phy.h |  262 +++++++
+ 5 files changed, 1645 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/dsa/mt7531_phy.c
+ create mode 100644 drivers/net/dsa/mt7531_phy.h
+
+diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
+index ae70b7962..0aa10bc3d 100644
+--- a/drivers/net/dsa/Makefile
++++ b/drivers/net/dsa/Makefile
+@@ -6,7 +6,8 @@ ifdef CONFIG_NET_DSA_LOOP
+ obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdinfo.o
+ endif
+ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
+-obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530.o
++obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530-dsa.o
++mt7530-dsa-objs			:= mt7530.o mt7531_phy.o
+ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+ obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
+ obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 008432d5c..e4c021eeb 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1829,6 +1829,8 @@ mt7531_setup(struct dsa_switch *ds)
  			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
  	}
  
@@ -11,20 +41,21 @@
  	/* Group and enable unused ports as a standalone dumb switch. */
  	setup_unused_ports(ds, unused_pm);
  
-Index: linux-5.4.124/drivers/net/dsa/mt7530.h
-===================================================================
---- linux-5.4.124.orig/drivers/net/dsa/mt7530.h
-+++ linux-5.4.124/drivers/net/dsa/mt7530.h
-@@ -782,4 +782,5 @@ static inline void INIT_MT7530_DUMMY_POL
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index aa758b2d2..8f1e827ff 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -782,4 +782,5 @@ static inline void INIT_MT7530_DUMMY_POLL(struct mt7530_dummy_poll *p,
  	p->reg = reg;
  }
  
 +int mt7531_phy_setup(struct dsa_switch *ds);
  #endif /* __MT7530_H */
-Index: linux-5.4.124/drivers/net/dsa/mt7531_phy.c
-===================================================================
+diff --git a/drivers/net/dsa/mt7531_phy.c b/drivers/net/dsa/mt7531_phy.c
+new file mode 100644
+index 000000000..a5c1e7d54
 --- /dev/null
-+++ linux-5.4.124/drivers/net/dsa/mt7531_phy.c
++++ b/drivers/net/dsa/mt7531_phy.c
 @@ -0,0 +1,1378 @@
 +// SPDX-License-Identifier:	GPL-2.0+
 +/*
@@ -1404,10 +1435,11 @@
 +
 +	return ret;
 +}
-Index: linux-5.4.124/drivers/net/dsa/mt7531_phy.h
-===================================================================
+diff --git a/drivers/net/dsa/mt7531_phy.h b/drivers/net/dsa/mt7531_phy.h
+new file mode 100644
+index 000000000..4cacabf54
 --- /dev/null
-+++ linux-5.4.124/drivers/net/dsa/mt7531_phy.h
++++ b/drivers/net/dsa/mt7531_phy.h
 @@ -0,0 +1,262 @@
 +/* SPDX-License-Identifier:	GPL-2.0+ */
 +/*
@@ -1671,17 +1703,6 @@
 +	DSP_MAX = 0x3e,
 +};
 +#endif /* _MT753X_REGS_H_ */
-Index: linux-5.4.124/drivers/net/dsa/Makefile
-===================================================================
---- linux-5.4.124.orig/drivers/net/dsa/Makefile
-+++ linux-5.4.124/drivers/net/dsa/Makefile
-@@ -6,7 +6,8 @@ ifdef CONFIG_NET_DSA_LOOP
- obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdinfo.o
- endif
- obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
--obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530.o
-+obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530-dsa.o
-+mt7530-dsa-objs			:= mt7530.o mt7531_phy.o
- obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
- obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
- obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1703-mxl-gpy-phy-support.patch
similarity index 96%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1703-mxl-gpy-phy-support.patch
index 5ff2798..056622a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1703-mxl-gpy-phy-support.patch
@@ -1,3 +1,17 @@
+From 4dad0228a64a810460928cd55c4dee0dd35708a0 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:32 +0800
+Subject: [PATCH] [networking][999-1703-mxl-gpy-phy-support.patch]
+
+---
+ drivers/net/phy/Kconfig   |   6 +
+ drivers/net/phy/Makefile  |   1 +
+ drivers/net/phy/mxl-gpy.c | 738 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 745 insertions(+)
+ create mode 100644 drivers/net/phy/mxl-gpy.c
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 45aaf7203..c0e09c99d 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
 @@ -516,6 +516,12 @@ config MARVELL_10G_PHY
@@ -13,9 +27,11 @@
  config MESON_GXL_PHY
  	tristate "Amlogic Meson GXL Internal PHY"
  	depends on ARCH_MESON || COMPILE_TEST
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 998de790e..8b57d6105 100644
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -95,6 +95,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c
+@@ -96,6 +96,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
  obj-$(CONFIG_LXT_PHY)		+= lxt.o
  obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
  obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
@@ -23,6 +39,9 @@
  obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
  obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)	+= mediatek-ge-soc.o
  obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
+diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
+new file mode 100644
+index 000000000..730427832
 --- /dev/null
 +++ b/drivers/net/phy/mxl-gpy.c
 @@ -0,0 +1,738 @@
@@ -764,3 +783,6 @@
 +MODULE_DESCRIPTION("Maxlinear Ethernet GPY Driver");
 +MODULE_AUTHOR("Xu Liang");
 +MODULE_LICENSE("GPL");
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1704-net-phy-aquantia-add-AQR113C.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1704-net-phy-aquantia-add-AQR113C.patch
index d99d75f..46960d6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1704-net-phy-aquantia-add-AQR113C.patch
@@ -1,5 +1,15 @@
+From 23e3cea0589cd65b9c405f23720e4ba8b1264cb3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:00 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1704-net-phy-aquantia-add-AQR113C.patch]
+
+---
+ drivers/net/phy/aquantia_main.c | 45 +++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 24 deletions(-)
+
 diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
-index 75d8351..ac8dd8e 100644
+index 75d8351ee..e7495c9a7 100644
 --- a/drivers/net/phy/aquantia_main.c
 +++ b/drivers/net/phy/aquantia_main.c
 @@ -22,6 +22,7 @@
@@ -10,7 +20,7 @@
  
  #define MDIO_PHYXS_VEND_IF_STATUS		0xe812
  #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK	GENMASK(7, 3)
-@@ -268,17 +268,6 @@ static int aqr_read_status(struct phy_device *phydev)
+@@ -303,17 +304,6 @@ static int aqr_read_status(struct phy_device *phydev)
  	return genphy_c45_read_status(phydev);
  }
  
@@ -28,7 +38,7 @@
  static int aqr107_read_rate(struct phy_device *phydev)
  {
  	int val;
-@@ -353,13 +342,7 @@ static int aqr107_read_status(struct phy_device *phydev)
+@@ -388,13 +378,7 @@ static int aqr107_read_status(struct phy_device *phydev)
  		break;
  	}
  
@@ -43,7 +53,7 @@
  	return aqr107_read_rate(phydev);
  }
  
-@@ -500,9 +483,6 @@ static int aqr107_config_init(struct phy_device *phydev)
+@@ -516,9 +500,6 @@ static int aqr107_config_init(struct phy_device *phydev)
  	if (!ret)
  		aqr107_chip_info(phydev);
  
@@ -53,7 +63,7 @@
  	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
  }
  
-@@ -527,9 +507,6 @@ static int aqcs109_config_init(struct phy_device *phydev)
+@@ -543,9 +524,6 @@ static int aqcs109_config_init(struct phy_device *phydev)
  	if (ret)
  		return ret;
  
@@ -63,7 +73,7 @@
  	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
  }
  
-@@ -695,6 +696,24 @@ static struct phy_driver aqr_driver[] = {
+@@ -695,6 +673,24 @@ static struct phy_driver aqr_driver[] = {
  	.ack_interrupt	= aqr_ack_interrupt,
  	.read_status	= aqr_read_status,
  },
@@ -88,7 +98,7 @@
  };
  
  module_phy_driver(aqr_driver);
-@@ -707,6 +726,7 @@ static struct mdio_device_id __maybe_unused aqr_tbl[] = {
+@@ -707,6 +703,7 @@ static struct mdio_device_id __maybe_unused aqr_tbl[] = {
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
  	{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
@@ -96,3 +106,6 @@
  	{ }
  };
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1705-add-netlink-support-for-dsa.patch
similarity index 84%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1705-add-netlink-support-for-dsa.patch
index 8853324..3f9adab 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1705-add-netlink-support-for-dsa.patch
@@ -1,8 +1,24 @@
-Index: linux-5.4.203/drivers/net/dsa/Makefile
-===================================================================
---- linux-5.4.203.orig/drivers/net/dsa/Makefile
-+++ linux-5.4.203/drivers/net/dsa/Makefile
-@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdi
+From 3e75ca66195dec023ca2e837ff748c317fd7ac26 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:00 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1705-add-netlink-support-for-dsa.patch]
+
+---
+ drivers/net/dsa/Makefile    |   2 +-
+ drivers/net/dsa/mt7530.c    |  24 ++-
+ drivers/net/dsa/mt7530.h    |   8 +
+ drivers/net/dsa/mt7530_nl.c | 311 ++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/mt7530_nl.h |  49 ++++++
+ 5 files changed, 386 insertions(+), 8 deletions(-)
+ create mode 100644 drivers/net/dsa/mt7530_nl.c
+ create mode 100644 drivers/net/dsa/mt7530_nl.h
+
+diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
+index 0aa10bc3d..ef563c6c1 100644
+--- a/drivers/net/dsa/Makefile
++++ b/drivers/net/dsa/Makefile
+@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdinfo.o
  endif
  obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
  obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530-dsa.o
@@ -11,40 +27,40 @@
  obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
  obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
  obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
-Index: linux-5.4.203/drivers/net/dsa/mt7530.c
-===================================================================
---- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
-+++ linux-5.4.203/drivers/net/dsa/mt7530.c
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index e4c021eeb..63f8a632b 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
 @@ -21,6 +21,7 @@
  #include <net/dsa.h>
-
+ 
  #include "mt7530.h"
 +#include "mt7530_nl.h"
-
+ 
  /* String, offset, and register size in bytes if different from 4 bytes */
  static const struct mt7530_mib_desc mt7530_mib[] = {
-@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv
+@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
  	return (hi << 16) | (lo & 0xffff);
  }
-
+ 
 -static void
 +void
  mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
  {
  	struct mii_bus *bus = priv->bus;
-@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p
+@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p)
  	return val;
  }
-
+ 
 -static u32
 +u32
  mt7530_read(struct mt7530_priv *priv, u32 reg)
  {
  	struct mt7530_dummy_poll p;
-@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_s
+@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum,
  	return mdiobus_write_nested(priv->bus, port, regnum, val);
  }
-
+ 
 -static int
 +int
  mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
@@ -53,7 +69,7 @@
 @@ -663,7 +664,7 @@ out:
  	return ret;
  }
-
+ 
 -static int
 +int
  mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
@@ -62,7 +78,7 @@
 @@ -711,7 +712,7 @@ out:
  	return ret;
  }
-
+ 
 -static int
 +int
  mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
@@ -71,24 +87,24 @@
 @@ -749,7 +750,7 @@ out:
  	return ret;
  }
-
+ 
 -static int
 +int
  mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
  			 u16 data)
  {
-@@ -2690,6 +2691,7 @@ mt7530_probe(struct mdio_device *mdiodev
+@@ -2691,6 +2692,7 @@ mt7530_probe(struct mdio_device *mdiodev)
  {
  	struct mt7530_priv *priv;
  	struct device_node *dn;
 +	int ret;
-
+ 
  	dn = mdiodev->dev.of_node;
-
-@@ -2765,7 +2767,13 @@ mt7530_probe(struct mdio_device *mdiodev
+ 
+@@ -2766,7 +2768,13 @@ mt7530_probe(struct mdio_device *mdiodev)
  	mutex_init(&priv->reg_mutex);
  	dev_set_drvdata(&mdiodev->dev, priv);
-
+ 
 -	return dsa_register_switch(priv->ds);
 +	ret = dsa_register_switch(priv->ds);
 +	if (ret)
@@ -98,24 +114,24 @@
 +
 +	return 0;
  }
-
+ 
  static void
-@@ -2786,6 +2794,8 @@ mt7530_remove(struct mdio_device *mdiode
-
+@@ -2787,6 +2795,8 @@ mt7530_remove(struct mdio_device *mdiodev)
+ 
  	dsa_unregister_switch(priv->ds);
  	mutex_destroy(&priv->reg_mutex);
 +
 +	mt7530_nl_exit();
  }
-
+ 
  static struct mdio_driver mt7530_mdio_driver = {
-Index: linux-5.4.203/drivers/net/dsa/mt7530.h
-===================================================================
---- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
-+++ linux-5.4.203/drivers/net/dsa/mt7530.h
-@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POL
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 8f1e827ff..130d7e5ec 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POLL(struct mt7530_dummy_poll *p,
  }
-
+ 
  int mt7531_phy_setup(struct dsa_switch *ds);
 +u32 mt7530_read(struct mt7530_priv *priv, u32 reg);
 +void mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val);
@@ -126,10 +142,11 @@
 +
 +
  #endif /* __MT7530_H */
-Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.c
-===================================================================
+diff --git a/drivers/net/dsa/mt7530_nl.c b/drivers/net/dsa/mt7530_nl.c
+new file mode 100644
+index 000000000..676adef70
 --- /dev/null
-+++ linux-5.4.203/drivers/net/dsa/mt7530_nl.c
++++ b/drivers/net/dsa/mt7530_nl.c
 @@ -0,0 +1,311 @@
 +// SPDX-License-Identifier: GPL-2.0

 +/*

@@ -442,10 +459,11 @@
 +	sw_priv = NULL;

 +	genl_unregister_family(&mt7530_nl_family);

 +}

-Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.h
-===================================================================
+diff --git a/drivers/net/dsa/mt7530_nl.h b/drivers/net/dsa/mt7530_nl.h
+new file mode 100644
+index 000000000..4619288c2
 --- /dev/null
-+++ linux-5.4.203/drivers/net/dsa/mt7530_nl.h
++++ b/drivers/net/dsa/mt7530_nl.h
 @@ -0,0 +1,49 @@
 +/* SPDX-License-Identifier: GPL-2.0-only */

 +/*

@@ -496,3 +514,6 @@
 +#endif /* __KERNEL__ */

 +

 +#endif /* _MT7530_NL_H_ */

+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1706-net-dsa-support-mt7988.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1706-net-dsa-support-mt7988.patch
index 7c468d8..c53c205 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1706-net-dsa-support-mt7988.patch
@@ -1,19 +1,30 @@
-Index: linux-5.4.203/drivers/net/dsa/mt7530.c
-===================================================================
---- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
-+++ linux-5.4.203/drivers/net/dsa/mt7530.c
+From 90508a46a0fd6416dcaad2c7f0ef25a5a421bf4f Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:00 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1706-net-dsa-support-mt7988.patch]
+
+---
+ drivers/net/dsa/mt7530.c | 191 ++++++++++++++++++++++++++++++++-------
+ drivers/net/dsa/mt7530.h |  11 ++-
+ 2 files changed, 164 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 63f8a632b..2cd5dae9c 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
 @@ -19,6 +19,7 @@
  #include <linux/reset.h>
  #include <linux/gpio/consumer.h>
  #include <net/dsa.h>
 +#include <linux/of_address.h>
-
+ 
  #include "mt7530.h"
  #include "mt7530_nl.h"
-@@ -170,28 +171,44 @@ core_clear(struct mt7530_priv *priv, u32
+@@ -170,28 +171,44 @@ core_clear(struct mt7530_priv *priv, u32 reg, u32 val)
  	core_rmw(priv, reg, val, 0);
  }
-
+ 
 +static void
 +mtk_w32(struct mt7530_priv *priv, u32 val, unsigned reg)
 +{
@@ -32,21 +43,12 @@
  	struct mii_bus *bus = priv->bus;
  	u16 page, r, lo, hi;
 -	int ret;
--
++	int ret = 0;
+ 
 -	page = (reg >> 6) & 0x3ff;
 -	r  = (reg >> 2) & 0xf;
 -	lo = val & 0xffff;
 -	hi = val >> 16;
--
--	/* MT7530 uses 31 as the pseudo port */
--	ret = bus->write(bus, 0x1f, 0x1f, page);
--	if (ret < 0)
--		goto err;
-+	int ret = 0;
-
--	ret = bus->write(bus, 0x1f, r,  lo);
--	if (ret < 0)
--		goto err;
 +	if (priv->direct_access){
 +		mtk_w32(priv, val, reg);
 +	} else {
@@ -54,26 +56,33 @@
 +		r  = (reg >> 2) & 0xf;
 +		lo = val & 0xffff;
 +		hi = val >> 16;
-+
+ 
+-	/* MT7530 uses 31 as the pseudo port */
+-	ret = bus->write(bus, 0x1f, 0x1f, page);
+-	if (ret < 0)
+-		goto err;
 +		/* MT7530 uses 31 as the pseudo port */
 +		ret = bus->write(bus, 0x1f, 0x1f, page);
 +		if (ret < 0)
 +			goto err;
-+
+ 
+-	ret = bus->write(bus, 0x1f, r,  lo);
+-	if (ret < 0)
+-		goto err;
 +		ret = bus->write(bus, 0x1f, r,  lo);
 +		if (ret < 0)
 +			goto err;
-
+ 
 -	ret = bus->write(bus, 0x1f, 0x10, hi);
 +		ret = bus->write(bus, 0x1f, 0x10, hi);
 +	}
  err:
  	if (ret < 0)
  		dev_err(&bus->dev,
-@@ -206,21 +223,25 @@ mt7530_mii_read(struct mt7530_priv *priv
+@@ -206,21 +223,25 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
  	u16 page, r, lo, hi;
  	int ret;
-
+ 
 -	page = (reg >> 6) & 0x3ff;
 -	r = (reg >> 2) & 0xf;
 +	if (priv->direct_access){
@@ -81,7 +90,7 @@
 +	} else {
 +		page = (reg >> 6) & 0x3ff;
 +		r = (reg >> 2) & 0xf;
-
+ 
 -	/* MT7530 uses 31 as the pseudo port */
 -	ret = bus->write(bus, 0x1f, 0x1f, page);
 -	if (ret < 0) {
@@ -96,19 +105,19 @@
 +				"failed to read mt7530 register\n");
 +			return ret;
 +		}
-
+ 
 -	lo = bus->read(bus, 0x1f, r);
 -	hi = bus->read(bus, 0x1f, 0x10);
 +		lo = bus->read(bus, 0x1f, r);
 +		hi = bus->read(bus, 0x1f, 0x10);
-
+ 
 -	return (hi << 16) | (lo & 0xffff);
 +		return (hi << 16) | (lo & 0xffff);
 +	}
  }
-
+ 
  void
-@@ -1906,9 +1927,9 @@ mt7531_phy_supported(struct dsa_switch *
+@@ -1907,9 +1928,9 @@ mt7531_phy_supported(struct dsa_switch *ds, int port,
  		if (mt7531_is_rgmii_port(priv, port))
  			return phy_interface_mode_is_rgmii(state->interface);
  		fallthrough;
@@ -121,7 +130,7 @@
  			goto unsupported;
  		break;
  	default:
-@@ -2017,6 +2038,13 @@ static void mt7531_sgmii_validate(struct
+@@ -2018,6 +2039,13 @@ static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port,
  		phylink_set(supported, 1000baseX_Full);
  		phylink_set(supported, 2500baseX_Full);
  		phylink_set(supported, 2500baseT_Full);
@@ -134,8 +143,8 @@
 +		phylink_set(supported, 10000baseER_Full);
  	}
  }
-
-@@ -2165,6 +2193,8 @@ mt7531_mac_config(struct dsa_switch *ds,
+ 
+@@ -2166,6 +2194,8 @@ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
  	case PHY_INTERFACE_MODE_NA:
  	case PHY_INTERFACE_MODE_1000BASEX:
  	case PHY_INTERFACE_MODE_2500BASEX:
@@ -143,8 +152,8 @@
 +	case PHY_INTERFACE_MODE_10GKR:
  		if (phylink_autoneg_inband(mode))
  			return -EINVAL;
-
-@@ -2302,8 +2332,8 @@ static void mt753x_phylink_mac_link_up(s
+ 
+@@ -2303,8 +2333,8 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
  	/* MT753x MAC works in 1G full duplex mode for all up-clocked
  	 * variants.
  	 */
@@ -155,10 +164,10 @@
  		speed = SPEED_1000;
  		duplex = DUPLEX_FULL;
  	}
-@@ -2402,8 +2432,8 @@ mt753x_phylink_validate(struct dsa_switc
-
+@@ -2403,8 +2433,8 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port,
+ 
  	phylink_set_port_modes(mask);
-
+ 
 -	if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
 -	    !phy_interface_mode_is_8023z(state->interface)) {
 +	if (state->interface != PHY_INTERFACE_MODE_TRGMII || state->interface != PHY_INTERFACE_MODE_USXGMII ||
@@ -166,10 +175,10 @@
  		phylink_set(mask, 10baseT_Half);
  		phylink_set(mask, 10baseT_Full);
  		phylink_set(mask, 100baseT_Half);
-@@ -2607,6 +2637,66 @@ mt753x_phy_write(struct dsa_switch *ds,
+@@ -2608,6 +2638,66 @@ mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
  	return priv->info->phy_write(ds, port, regnum, val);
  }
-
+ 
 +static int
 +mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
 +{
@@ -233,7 +242,7 @@
  static const struct dsa_switch_ops mt7530_switch_ops = {
  	.get_tag_protocol	= mtk_get_tag_protocol,
  	.setup			= mt753x_setup,
-@@ -2676,12 +2766,28 @@ static const struct mt753x_info mt753x_t
+@@ -2677,12 +2767,28 @@ static const struct mt753x_info mt753x_table[] = {
  		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
  		.mac_pcs_link_up = mt7531_sgmii_link_up_force,
  	},
@@ -253,7 +262,7 @@
 +	},
 +
  };
-
+ 
  static const struct of_device_id mt7530_of_match[] = {
  	{ .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
  	{ .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
@@ -262,18 +271,18 @@
  	{ /* sentinel */ },
  };
  MODULE_DEVICE_TABLE(of, mt7530_of_match);
-@@ -2691,6 +2797,7 @@ mt7530_probe(struct mdio_device *mdiodev
+@@ -2692,6 +2798,7 @@ mt7530_probe(struct mdio_device *mdiodev)
  {
  	struct mt7530_priv *priv;
  	struct device_node *dn;
 +	struct device_node *switch_node = NULL;
  	int ret;
-
+ 
  	dn = mdiodev->dev.of_node;
-@@ -2760,6 +2867,16 @@ mt7530_probe(struct mdio_device *mdiodev
+@@ -2761,6 +2868,16 @@ mt7530_probe(struct mdio_device *mdiodev)
  		}
  	}
-
+ 
 +	switch_node = of_find_node_by_name(NULL, "switch0");
 +	if(switch_node) {
 +		priv->base = of_iomap(switch_node, 0);
@@ -287,48 +296,47 @@
  	priv->bus = mdiodev->bus;
  	priv->dev = &mdiodev->dev;
  	priv->ds->priv = priv;
-@@ -2768,9 +2885,12 @@ mt7530_probe(struct mdio_device *mdiodev
+@@ -2769,9 +2886,12 @@ mt7530_probe(struct mdio_device *mdiodev)
  	dev_set_drvdata(&mdiodev->dev, priv);
-
+ 
  	ret = dsa_register_switch(priv->ds);
 -	if (ret)
 -		return ret;
--
 +	if (ret) {
 +		if(priv->base)
 +			iounmap(priv->base);
-+
+ 
 +		return ret;
 +	}
  	mt7530_nl_init(&priv);
-
+ 
  	return 0;
-@@ -2795,6 +2915,9 @@ mt7530_remove(struct mdio_device *mdiode
+@@ -2796,6 +2916,9 @@ mt7530_remove(struct mdio_device *mdiodev)
  	dsa_unregister_switch(priv->ds);
  	mutex_destroy(&priv->reg_mutex);
-
+ 
 +	if(priv->base)
 +		iounmap(priv->base);
 +
  	mt7530_nl_exit();
  }
-
-Index: linux-5.4.203/drivers/net/dsa/mt7530.h
-===================================================================
---- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
-+++ linux-5.4.203/drivers/net/dsa/mt7530.h
+ 
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 130d7e5ec..7b175c5f2 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
 @@ -16,6 +16,7 @@ enum mt753x_id {
  	ID_MT7530 = 0,
  	ID_MT7621 = 1,
  	ID_MT7531 = 2,
 +	ID_MT7988 = 3,
  };
-
+ 
  #define	NUM_TRGMII_CTRL			5
 @@ -51,11 +52,11 @@ enum mt753x_id {
  #define  MT7531_MIRROR_PORT_SET(x)	(((x) & MIRROR_MASK) << 16)
  #define  MT7531_CPU_PMAP_MASK		GENMASK(7, 0)
-
+ 
 -#define MT753X_MIRROR_REG(id)		(((id) == ID_MT7531) ? \
 +#define MT753X_MIRROR_REG(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
  					 MT7531_CFC : MT7530_MFC)
@@ -338,7 +346,7 @@
 -#define MT753X_MIRROR_MASK(id)		(((id) == ID_MT7531) ? \
 +#define MT753X_MIRROR_MASK(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
  					 MT7531_MIRROR_MASK : MIRROR_MASK)
-
+ 
  /* Registers for BPDU and PAE frame control*/
 @@ -261,7 +262,7 @@ enum mt7530_vlan_port_attr {
  					 MT7531_FORCE_DPX | \
@@ -358,3 +366,6 @@
  	const struct mt753x_info *info;
  	unsigned int		id;
  	bool			mcm;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-gphy-calibration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1707-add-mdio-bus-for-gphy-calibration.patch
old mode 100755
new mode 100644
similarity index 82%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-gphy-calibration.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1707-add-mdio-bus-for-gphy-calibration.patch
index e3efa34..cfa2a0c
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-gphy-calibration.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1707-add-mdio-bus-for-gphy-calibration.patch
@@ -1,11 +1,21 @@
-Index: linux-5.4.215/drivers/net/dsa/mt7530.c
-===================================================================
---- linux-5.4.215.orig/drivers/net/dsa/mt7530.c
-+++ linux-5.4.215/drivers/net/dsa/mt7530.c
-@@ -847,6 +847,117 @@ mt7531_ind_phy_write(struct dsa_switch *
+From c816d165754d8fd002478cce6eb774b9390c795f Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:01 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1707-add-mdio-bus-for-gphy-calibration.patch]
+
+---
+ drivers/net/dsa/mt7530.c | 115 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 115 insertions(+)
+
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 2cd5dae9c..290a2e77a 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -847,6 +847,117 @@ mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum,
  	return ret;
  }
-
+ 
 +static int mt753x_mdio_read(struct mii_bus *bus, int addr, int regnum)
 +{
 +	struct mt7530_priv *priv = bus->priv;
@@ -120,14 +130,17 @@
  static void
  mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  		   uint8_t *data)
-@@ -2694,6 +2805,10 @@ mt7988_setup(struct dsa_switch *ds)
+@@ -2695,6 +2806,10 @@ mt7988_setup(struct dsa_switch *ds)
  	if (ret < 0)
  		return ret;
-
+ 
 +	ret = mt753x_setup_mdio(ds);
 +	if (ret < 0)
 +		dev_err(priv->dev, "mt753x_setup_mdio failed\n");
 +
  	return 0;
  }
+ 
+-- 
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/754-net-phy-add-5GBASER.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1708-net-phy-add-5GBASER.patch
similarity index 72%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/754-net-phy-add-5GBASER.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1708-net-phy-add-5GBASER.patch
index 8165303..b112bdb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/754-net-phy-add-5GBASER.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1708-net-phy-add-5GBASER.patch
@@ -1,16 +1,29 @@
+From 4df7f1c284d2c63bc78c2a517e510a8d250dd4c4 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:01 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1708-net-phy-add-5GBASER.patch]
+
+---
+ drivers/net/phy/marvell10g.c | 4 ++++
+ drivers/net/phy/phylink.c    | 4 ++++
+ drivers/net/phy/sfp-bus.c    | 3 +++
+ include/linux/phy.h          | 3 +++
+ 4 files changed, 14 insertions(+)
+
 diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
-index daed73a..7d080d5 100644
+index 512f27b0b..1e4631761 100644
 --- a/drivers/net/phy/marvell10g.c
 +++ b/drivers/net/phy/marvell10g.c
-@@ -516,6 +516,7 @@ static void mv3310_update_interface(struct phy_device *phydev)
- 
+@@ -386,6 +386,7 @@ static void mv3310_update_interface(struct phy_device *phydev)
+ {
  	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
  	     phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
 +	     phydev->interface == PHY_INTERFACE_MODE_5GBASER ||
  	     phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
  		/* The PHY automatically switches its serdes interface (and
  		 * active PHYXS instance) between Cisco SGMII, 10GBase-KR and
-@@ -527,6 +528,9 @@ static void mv3310_update_interface(struct phy_device *phydev)
+@@ -397,6 +398,9 @@ static void mv3310_update_interface(struct phy_device *phydev)
  		case SPEED_10000:
  			phydev->interface = PHY_INTERFACE_MODE_10GKR;
  			break;
@@ -21,7 +34,7 @@
  			phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
  			break;
 diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
-index b3f25a9..6a38a1c 100644
+index b3f25a939..f360d9225 100644
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
 @@ -299,6 +299,10 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
@@ -36,10 +49,10 @@
  			phylink_set(pl->supported, 10baseT_Half);
  			phylink_set(pl->supported, 10baseT_Full);
 diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
-index 0d5ac2a..a702c9b 100644
+index 42f0441f2..a2f451c31 100644
 --- a/drivers/net/phy/sfp-bus.c
 +++ b/drivers/net/phy/sfp-bus.c
-@@ -302,6 +302,9 @@ phy_interface_t sfp_select_interface(struct sfp_bus *bus,
+@@ -389,6 +389,9 @@ phy_interface_t sfp_select_interface(struct sfp_bus *bus,
  	    phylink_test(link_modes, 10000baseT_Full))
  		return PHY_INTERFACE_MODE_10GKR;
  
@@ -50,10 +63,10 @@
  		return PHY_INTERFACE_MODE_2500BASEX;
  
 diff --git a/include/linux/phy.h b/include/linux/phy.h
-index 34bdd16..77fad08 100644
+index 19444cd96..a1070d60e 100644
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -98,6 +98,7 @@ typedef enum {
+@@ -97,6 +97,7 @@ typedef enum {
  	PHY_INTERFACE_MODE_TRGMII,
  	PHY_INTERFACE_MODE_1000BASEX,
  	PHY_INTERFACE_MODE_2500BASEX,
@@ -61,7 +74,7 @@
  	PHY_INTERFACE_MODE_RXAUI,
  	PHY_INTERFACE_MODE_XAUI,
  	/* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */
-@@ -172,6 +173,8 @@ static inline const char *phy_modes(phy_interface_t interface)
+@@ -171,6 +172,8 @@ static inline const char *phy_modes(phy_interface_t interface)
  		return "1000base-x";
  	case PHY_INTERFACE_MODE_2500BASEX:
  		return "2500base-x";
@@ -70,3 +83,6 @@
  	case PHY_INTERFACE_MODE_RXAUI:
  		return "rxaui";
  	case PHY_INTERFACE_MODE_XAUI:
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1709-net-phy-sfp-add-rollball-support.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1709-net-phy-sfp-add-rollball-support.patch
index 5a6e865..bac49cf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1709-net-phy-sfp-add-rollball-support.patch
@@ -1,270 +1,575 @@
---- a/drivers/net/phy/mdio-i2c.c
-+++ b/drivers/net/phy/mdio-i2c.c
-@@ -12,6 +12,7 @@
- #include <linux/i2c.h>
- #include <linux/mdio/mdio-i2c.h>
- #include <linux/phy.h>
-+#include <linux/sfp.h>
+From 1631a36b9ac022ce6ffb58b039a7e85ad3414ed5 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:01 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1709-net-phy-sfp-add-rollball-support.patch]
+
+---
+ drivers/net/phy/marvell.c     |   2 +-
+ drivers/net/phy/marvell10g.c  | 168 +++++++++++++--
+ drivers/net/phy/mdio-i2c.c    | 309 +++++++++++++++++++++++++++-
+ drivers/net/phy/phylink.c     |  74 +++++--
+ drivers/net/phy/sfp-bus.c     | 102 +---------
+ drivers/net/phy/sfp.c         | 373 +++++++++++++++++++++++++++++-----
+ drivers/net/phy/sfp.h         |  11 +-
+ include/linux/mdio/mdio-i2c.h |  10 +-
+ 8 files changed, 874 insertions(+), 175 deletions(-)
+
+diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
+index 49801c2eb..f25881745 100644
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -2175,7 +2175,7 @@ static struct phy_driver marvell_drivers[] = {
+ 		.phy_id = MARVELL_PHY_ID_88E1111,
+ 		.phy_id_mask = MARVELL_PHY_ID_MASK,
+ 		.name = "Marvell 88E1111",
+-		/* PHY_GBIT_FEATURES */
++		.features = PHY_GBIT_FEATURES,
+ 		.probe = marvell_probe,
+ 		.config_init = &m88e1111_config_init,
+ 		.config_aneg = &marvell_config_aneg,
+diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
+index 1e4631761..7d080d52e 100644
+--- a/drivers/net/phy/marvell10g.c
++++ b/drivers/net/phy/marvell10g.c
+@@ -32,6 +32,15 @@
+ #define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
  
- /*
-  * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
-@@ -28,7 +29,7 @@ static unsigned int i2c_mii_phy_addr(int
- 	return phy_id + 0x40;
- }
+ enum {
++	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
++	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
++	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
++	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
++	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+ 	MV_PMA_BOOT		= 0xc050,
+ 	MV_PMA_BOOT_FATAL	= BIT(0),
  
--static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
-+static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
- {
- 	struct i2c_adapter *i2c = bus->priv;
- 	struct i2c_msg msgs[2];
-@@ -62,7 +63,8 @@ static int i2c_mii_read(struct mii_bus *
- 	return data[0] << 8 | data[1];
- }
+@@ -53,7 +62,18 @@ enum {
  
--static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
-+static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
-+				 u16 val)
- {
- 	struct i2c_adapter *i2c = bus->priv;
- 	struct i2c_msg msg;
-@@ -91,9 +93,288 @@ static int i2c_mii_write(struct mii_bus
- 	return ret < 0 ? ret : 0;
- }
+ 	/* Vendor2 MMD registers */
+ 	MV_V2_PORT_CTRL		= 0xf001,
+-	MV_V2_PORT_CTRL_PWRDOWN = 0x0800,
++	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
++	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
++	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
++	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
++	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
++	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
++	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
+ 	MV_V2_TEMP_CTRL		= 0xf08a,
+ 	MV_V2_TEMP_CTRL_MASK	= 0xc000,
+ 	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
+@@ -62,11 +82,24 @@ enum {
+ 	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+ };
  
--struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
-+/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
-+ * instead via address 0x51, when SFP page is set to 0x03 and password to
-+ * 0xffffffff.
-+ *
-+ * address  size  contents  description
-+ * -------  ----  --------  -----------
-+ * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
-+ * 0x81     1     DEV       Clause 45 device
-+ * 0x82     2     REG       Clause 45 register
-+ * 0x84     2     VAL       Register value
-+ */
-+#define ROLLBALL_PHY_I2C_ADDR		0x51
-+
-+#define ROLLBALL_PASSWORD		(SFP_VSL + 3)
-+
-+#define ROLLBALL_CMD_ADDR		0x80
-+#define ROLLBALL_DATA_ADDR		0x81
-+
-+#define ROLLBALL_CMD_WRITE		0x01
-+#define ROLLBALL_CMD_READ		0x02
-+#define ROLLBALL_CMD_DONE		0x04
++struct mv3310_chip {
++	int (*get_mactype)(struct phy_device *phydev);
++	int (*init_interface)(struct phy_device *phydev, int mactype);
++};
 +
-+#define SFP_PAGE_ROLLBALL_MDIO		3
+ struct mv3310_priv {
++	bool rate_match;
++	phy_interface_t const_interface;
 +
-+static int __i2c_transfer_err(struct i2c_adapter *i2c, struct i2c_msg *msgs,
-+			      int num)
+ 	struct device *hwmon_dev;
+ 	char *hwmon_name;
+ };
+ 
++static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
 +{
-+	int ret;
-+
-+	ret = __i2c_transfer(i2c, msgs, num);
-+	if (ret < 0)
-+		return ret;
-+	else if (ret != num)
-+		return -EIO;
-+	else
-+		return 0;
++	return phydev->drv->driver_data;
 +}
 +
-+static int __i2c_rollball_get_page(struct i2c_adapter *i2c, int bus_addr,
-+				   u8 *page)
+ #ifdef CONFIG_HWMON
+ static umode_t mv3310_hwmon_is_visible(const void *data,
+ 				       enum hwmon_sensor_types type,
+@@ -155,13 +188,6 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
+ 			      MV_V2_TEMP_CTRL_MASK, val);
+ }
+ 
+-static void mv3310_hwmon_disable(void *data)
+-{
+-	struct phy_device *phydev = data;
+-
+-	mv3310_hwmon_config(phydev, false);
+-}
+-
+ static int mv3310_hwmon_probe(struct phy_device *phydev)
+ {
+ 	struct device *dev = &phydev->mdio.dev;
+@@ -185,10 +211,6 @@ static int mv3310_hwmon_probe(struct phy_device *phydev)
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
+-	if (ret)
+-		return ret;
+-
+ 	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
+ 				priv->hwmon_name, phydev,
+ 				&mv3310_hwmon_chip_info, NULL);
+@@ -262,6 +284,11 @@ static int mv3310_probe(struct phy_device *phydev)
+ 	return phy_sfp_probe(phydev, &mv3310_sfp_ops);
+ }
+ 
++static void mv3310_remove(struct phy_device *phydev)
 +{
-+	struct i2c_msg msgs[2];
-+	u8 addr = SFP_PAGE;
-+
-+	msgs[0].addr = bus_addr;
-+	msgs[0].flags = 0;
-+	msgs[0].len = 1;
-+	msgs[0].buf = &addr;
-+
-+	msgs[1].addr = bus_addr;
-+	msgs[1].flags = I2C_M_RD;
-+	msgs[1].len = 1;
-+	msgs[1].buf = page;
-+
-+	return __i2c_transfer_err(i2c, msgs, 2);
++	mv3310_hwmon_config(phydev, false);
 +}
 +
-+static int __i2c_rollball_set_page(struct i2c_adapter *i2c, int bus_addr,
-+				   u8 page)
+ static int mv3310_suspend(struct phy_device *phydev)
+ {
+ 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+@@ -297,8 +324,84 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
+ 		MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
+ }
+ 
++static int mv2110_get_mactype(struct phy_device *phydev)
 +{
-+	struct i2c_msg msg;
-+	u8 buf[2];
-+
-+	buf[0] = SFP_PAGE;
-+	buf[1] = page;
++	int mactype;
 +
-+	msg.addr = bus_addr;
-+	msg.flags = 0;
-+	msg.len = 2;
-+	msg.buf = buf;
++	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
++	if (mactype < 0)
++		return mactype;
 +
-+	return __i2c_transfer_err(i2c, &msg, 1);
++	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
 +}
 +
-+/* In order to not interfere with other SFP code (which possibly may manipulate
-+ * SFP_PAGE), for every transfer we do this:
-+ *   1. lock the bus
-+ *   2. save content of SFP_PAGE
-+ *   3. set SFP_PAGE to 3
-+ *   4. do the transfer
-+ *   5. restore original SFP_PAGE
-+ *   6. unlock the bus
-+ * Note that one might think that steps 2 to 5 could be theoretically done all
-+ * in one call to i2c_transfer (by constructing msgs array in such a way), but
-+ * unfortunately tests show that this does not work :-( Changed SFP_PAGE does
-+ * not take into account until i2c_transfer() is done.
-+ */
-+static int i2c_transfer_rollball(struct i2c_adapter *i2c,
-+				 struct i2c_msg *msgs, int num)
++static int mv3310_get_mactype(struct phy_device *phydev)
 +{
-+	int ret, main_err = 0;
-+	u8 saved_page;
++	int mactype;
 +
-+	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
++	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
++	if (mactype < 0)
++		return mactype;
 +
-+	/* save original page */
-+	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
-+	if (ret)
-+		goto unlock;
++	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
++}
 +
-+	/* change to RollBall MDIO page */
-+	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
-+	if (ret)
-+		goto unlock;
++static int mv2110_init_interface(struct phy_device *phydev, int mactype)
++{
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
 +
-+	/* do the transfer; we try to restore original page if this fails */
-+	ret = __i2c_transfer_err(i2c, msgs, num);
-+	if (ret)
-+		main_err = ret;
++	priv->rate_match = false;
 +
-+	/* restore original page */
-+	ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
++	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
++		priv->rate_match = true;
 +
-+unlock:
-+	i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
++	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII)
++		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
++	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
++		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
++	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER ||
++		 mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN)
++		priv->const_interface = PHY_INTERFACE_MODE_NA;
++	else
++		return -EINVAL;
 +
-+	return main_err ? : ret;
++	return 0;
 +}
 +
-+static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
-+				 size_t len)
++static int mv3310_init_interface(struct phy_device *phydev, int mactype)
 +{
-+	struct i2c_adapter *i2c = bus->priv;
-+	struct i2c_msg msgs[2];
-+	u8 cmd_addr, tmp, *res;
-+	int i, ret;
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
 +
-+	cmd_addr = ROLLBALL_CMD_ADDR;
++	priv->rate_match = false;
 +
-+	res = buf ? buf : &tmp;
-+	len = buf ? len : 1;
++	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
++	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
++	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
++		priv->rate_match = true;
 +
-+	msgs[0].addr = bus_addr;
-+	msgs[0].flags = 0;
-+	msgs[0].len = 1;
-+	msgs[0].buf = &cmd_addr;
++	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII)
++		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
++	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER)
++		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
++	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
++		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI)
++		priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
++	else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH ||
++		 mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI)
++		priv->const_interface = PHY_INTERFACE_MODE_XAUI;
++	else
++		return -EINVAL;
 +
-+	msgs[1].addr = bus_addr;
-+	msgs[1].flags = I2C_M_RD;
-+	msgs[1].len = len;
-+	msgs[1].buf = res;
++	return 0;
++}
 +
-+	/* By experiment it takes up to 70 ms to access a register for these
-+	 * SFPs. Sleep 20ms between iterations and try 10 times.
-+	 */
-+	i = 10;
-+	do {
-+		msleep(20);
+ static int mv3310_config_init(struct phy_device *phydev)
+ {
++	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
++	int err, mactype;
 +
-+		ret = i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
-+		if (ret)
-+			return ret;
+ 	/* Check that the PHY interface type is compatible */
+ 	if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ 	    phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
+@@ -307,6 +410,16 @@ static int mv3310_config_init(struct phy_device *phydev)
+ 	    phydev->interface != PHY_INTERFACE_MODE_10GKR)
+ 		return -ENODEV;
+ 
++	mactype = chip->get_mactype(phydev);
++	if (mactype < 0)
++		return mactype;
 +
-+		if (*res == ROLLBALL_CMD_DONE)
-+			return 0;
-+	} while (i-- > 0);
++	err = chip->init_interface(phydev, mactype);
++	if (err) {
++		phydev_err(phydev, "MACTYPE configuration invalid\n");
++		return err;
++	}
 +
-+	dev_info(&bus->dev, "poll timed out\n");
+ 	return 0;
+ }
+ 
+@@ -384,6 +497,23 @@ static int mv3310_aneg_done(struct phy_device *phydev)
+ 
+ static void mv3310_update_interface(struct phy_device *phydev)
+ {
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
 +
-+	return -ETIMEDOUT;
-+}
++	if (!phydev->link)
++		return;
 +
-+static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
-+				u8 *data, size_t len)
-+{
-+	struct i2c_adapter *i2c = bus->priv;
-+	struct i2c_msg msgs[2];
-+	u8 cmdbuf[2];
++	/* In all of the "* with Rate Matching" modes the PHY interface is fixed
++	 * at 10Gb. The PHY adapts the rate to actual wire speed with help of
++	 * internal 16KB buffer.
++	 *
++	 * In USXGMII mode the PHY interface mode is also fixed.
++	 */
++	if (priv->rate_match ||
++	    priv->const_interface == PHY_INTERFACE_MODE_USXGMII) {
++		phydev->interface = priv->const_interface;
++		return;
++	}
 +
-+	cmdbuf[0] = ROLLBALL_CMD_ADDR;
-+	cmdbuf[1] = cmd;
+ 	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
+ 	     phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
+ 	     phydev->interface == PHY_INTERFACE_MODE_5GBASER ||
+@@ -503,11 +633,22 @@ static int mv3310_read_status(struct phy_device *phydev)
+ 	return 0;
+ }
+ 
++static const struct mv3310_chip mv3310_type = {
++	.get_mactype = mv3310_get_mactype,
++	.init_interface = mv3310_init_interface,
++};
 +
-+	msgs[0].addr = bus_addr;
-+	msgs[0].flags = 0;
-+	msgs[0].len = len;
-+	msgs[0].buf = data;
++static const struct mv3310_chip mv2111_type = {
++	.get_mactype = mv2110_get_mactype,
++	.init_interface = mv2110_init_interface,
++};
 +
-+	msgs[1].addr = bus_addr;
-+	msgs[1].flags = 0;
-+	msgs[1].len = sizeof(cmdbuf);
-+	msgs[1].buf = cmdbuf;
+ static struct phy_driver mv3310_drivers[] = {
+ 	{
+ 		.phy_id		= MARVELL_PHY_ID_88X3310,
+ 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
+ 		.name		= "mv88x3310",
++		.driver_data	= &mv3310_type,
+ 		.get_features	= mv3310_get_features,
+ 		.soft_reset	= genphy_no_soft_reset,
+ 		.config_init	= mv3310_config_init,
+@@ -517,11 +658,13 @@ static struct phy_driver mv3310_drivers[] = {
+ 		.config_aneg	= mv3310_config_aneg,
+ 		.aneg_done	= mv3310_aneg_done,
+ 		.read_status	= mv3310_read_status,
++		.remove		= mv3310_remove,
+ 	},
+ 	{
+ 		.phy_id		= MARVELL_PHY_ID_88E2110,
+ 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
+ 		.name		= "mv88x2110",
++		.driver_data	= &mv2111_type,
+ 		.probe		= mv3310_probe,
+ 		.suspend	= mv3310_suspend,
+ 		.resume		= mv3310_resume,
+@@ -530,6 +673,7 @@ static struct phy_driver mv3310_drivers[] = {
+ 		.config_aneg	= mv3310_config_aneg,
+ 		.aneg_done	= mv3310_aneg_done,
+ 		.read_status	= mv3310_read_status,
++		.remove		= mv3310_remove,
+ 	},
+ };
+ 
+diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c
+index 09200a70b..85db63c33 100644
+--- a/drivers/net/phy/mdio-i2c.c
++++ b/drivers/net/phy/mdio-i2c.c
+@@ -12,6 +12,7 @@
+ #include <linux/i2c.h>
+ #include <linux/mdio/mdio-i2c.h>
+ #include <linux/phy.h>
++#include <linux/sfp.h>
+ 
+ /*
+  * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
+@@ -28,7 +29,7 @@ static unsigned int i2c_mii_phy_addr(int phy_id)
+ 	return phy_id + 0x40;
+ }
+ 
+-static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
++static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
+ {
+ 	struct i2c_adapter *i2c = bus->priv;
+ 	struct i2c_msg msgs[2];
+@@ -62,7 +63,8 @@ static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
+ 	return data[0] << 8 | data[1];
+ }
+ 
+-static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
++static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
++				 u16 val)
+ {
+ 	struct i2c_adapter *i2c = bus->priv;
+ 	struct i2c_msg msg;
+@@ -91,9 +93,288 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+ 	return ret < 0 ? ret : 0;
+ }
+ 
+-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
++/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
++ * instead via address 0x51, when SFP page is set to 0x03 and password to
++ * 0xffffffff.
++ *
++ * address  size  contents  description
++ * -------  ----  --------  -----------
++ * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
++ * 0x81     1     DEV       Clause 45 device
++ * 0x82     2     REG       Clause 45 register
++ * 0x84     2     VAL       Register value
++ */
++#define ROLLBALL_PHY_I2C_ADDR		0x51
 +
-+	return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
-+}
++#define ROLLBALL_PASSWORD		(SFP_VSL + 3)
 +
-+static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
-+{
-+	u8 buf[4], res[6];
-+	int bus_addr, ret;
-+	u16 val;
++#define ROLLBALL_CMD_ADDR		0x80
++#define ROLLBALL_DATA_ADDR		0x81
 +
-+	if (!(reg & MII_ADDR_C45))
-+		return -EOPNOTSUPP;
++#define ROLLBALL_CMD_WRITE		0x01
++#define ROLLBALL_CMD_READ		0x02
++#define ROLLBALL_CMD_DONE		0x04
 +
-+	bus_addr = i2c_mii_phy_addr(phy_id);
-+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
-+		return 0xffff;
++#define SFP_PAGE_ROLLBALL_MDIO		3
 +
-+	buf[0] = ROLLBALL_DATA_ADDR;
-+	buf[1] = (reg >> 16) & 0x1f;
-+	buf[2] = (reg >> 8) & 0xff;
-+	buf[3] = reg & 0xff;
++static int __i2c_transfer_err(struct i2c_adapter *i2c, struct i2c_msg *msgs,
++			      int num)
++{
++	int ret;
 +
-+	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_READ, buf,
-+				   sizeof(buf));
++	ret = __i2c_transfer(i2c, msgs, num);
 +	if (ret < 0)
 +		return ret;
++	else if (ret != num)
++		return -EIO;
++	else
++		return 0;
++}
 +
-+	ret = i2c_rollball_mii_poll(bus, bus_addr, res, sizeof(res));
-+	if (ret == -ETIMEDOUT)
-+		return 0xffff;
-+	else if (ret < 0)
-+		return ret;
++static int __i2c_rollball_get_page(struct i2c_adapter *i2c, int bus_addr,
++				   u8 *page)
++{
++	struct i2c_msg msgs[2];
++	u8 addr = SFP_PAGE;
 +
-+	val = res[4] << 8 | res[5];
++	msgs[0].addr = bus_addr;
++	msgs[0].flags = 0;
++	msgs[0].len = 1;
++	msgs[0].buf = &addr;
 +
-+	return val;
++	msgs[1].addr = bus_addr;
++	msgs[1].flags = I2C_M_RD;
++	msgs[1].len = 1;
++	msgs[1].buf = page;
++
++	return __i2c_transfer_err(i2c, msgs, 2);
 +}
 +
-+static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
-+				  u16 val)
++static int __i2c_rollball_set_page(struct i2c_adapter *i2c, int bus_addr,
++				   u8 page)
 +{
-+	int bus_addr, ret;
-+	u8 buf[6];
++	struct i2c_msg msg;
++	u8 buf[2];
 +
-+	if (!(reg & MII_ADDR_C45))
-+		return -EOPNOTSUPP;
++	buf[0] = SFP_PAGE;
++	buf[1] = page;
 +
-+	bus_addr = i2c_mii_phy_addr(phy_id);
-+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
-+		return 0;
++	msg.addr = bus_addr;
++	msg.flags = 0;
++	msg.len = 2;
++	msg.buf = buf;
 +
-+	buf[0] = ROLLBALL_DATA_ADDR;
++	return __i2c_transfer_err(i2c, &msg, 1);
++}
++
++/* In order to not interfere with other SFP code (which possibly may manipulate
++ * SFP_PAGE), for every transfer we do this:
++ *   1. lock the bus
++ *   2. save content of SFP_PAGE
++ *   3. set SFP_PAGE to 3
++ *   4. do the transfer
++ *   5. restore original SFP_PAGE
++ *   6. unlock the bus
++ * Note that one might think that steps 2 to 5 could be theoretically done all
++ * in one call to i2c_transfer (by constructing msgs array in such a way), but
++ * unfortunately tests show that this does not work :-( Changed SFP_PAGE does
++ * not take into account until i2c_transfer() is done.
++ */
++static int i2c_transfer_rollball(struct i2c_adapter *i2c,
++				 struct i2c_msg *msgs, int num)
++{
++	int ret, main_err = 0;
++	u8 saved_page;
++
++	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
++
++	/* save original page */
++	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
++	if (ret)
++		goto unlock;
++
++	/* change to RollBall MDIO page */
++	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
++	if (ret)
++		goto unlock;
++
++	/* do the transfer; we try to restore original page if this fails */
++	ret = __i2c_transfer_err(i2c, msgs, num);
++	if (ret)
++		main_err = ret;
++
++	/* restore original page */
++	ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
++
++unlock:
++	i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
++
++	return main_err ? : ret;
++}
++
++static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
++				 size_t len)
++{
++	struct i2c_adapter *i2c = bus->priv;
++	struct i2c_msg msgs[2];
++	u8 cmd_addr, tmp, *res;
++	int i, ret;
++
++	cmd_addr = ROLLBALL_CMD_ADDR;
++
++	res = buf ? buf : &tmp;
++	len = buf ? len : 1;
++
++	msgs[0].addr = bus_addr;
++	msgs[0].flags = 0;
++	msgs[0].len = 1;
++	msgs[0].buf = &cmd_addr;
++
++	msgs[1].addr = bus_addr;
++	msgs[1].flags = I2C_M_RD;
++	msgs[1].len = len;
++	msgs[1].buf = res;
++
++	/* By experiment it takes up to 70 ms to access a register for these
++	 * SFPs. Sleep 20ms between iterations and try 10 times.
++	 */
++	i = 10;
++	do {
++		msleep(20);
++
++		ret = i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
++		if (ret)
++			return ret;
++
++		if (*res == ROLLBALL_CMD_DONE)
++			return 0;
++	} while (i-- > 0);
++
++	dev_info(&bus->dev, "poll timed out\n");
++
++	return -ETIMEDOUT;
++}
++
++static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
++				u8 *data, size_t len)
++{
++	struct i2c_adapter *i2c = bus->priv;
++	struct i2c_msg msgs[2];
++	u8 cmdbuf[2];
++
++	cmdbuf[0] = ROLLBALL_CMD_ADDR;
++	cmdbuf[1] = cmd;
++
++	msgs[0].addr = bus_addr;
++	msgs[0].flags = 0;
++	msgs[0].len = len;
++	msgs[0].buf = data;
++
++	msgs[1].addr = bus_addr;
++	msgs[1].flags = 0;
++	msgs[1].len = sizeof(cmdbuf);
++	msgs[1].buf = cmdbuf;
++
++	return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
++}
++
++static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
++{
++	u8 buf[4], res[6];
++	int bus_addr, ret;
++	u16 val;
++
++	if (!(reg & MII_ADDR_C45))
++		return -EOPNOTSUPP;
++
++	bus_addr = i2c_mii_phy_addr(phy_id);
++	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
++		return 0xffff;
++
++	buf[0] = ROLLBALL_DATA_ADDR;
++	buf[1] = (reg >> 16) & 0x1f;
++	buf[2] = (reg >> 8) & 0xff;
++	buf[3] = reg & 0xff;
++
++	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_READ, buf,
++				   sizeof(buf));
++	if (ret < 0)
++		return ret;
++
++	ret = i2c_rollball_mii_poll(bus, bus_addr, res, sizeof(res));
++	if (ret == -ETIMEDOUT)
++		return 0xffff;
++	else if (ret < 0)
++		return ret;
++
++	val = res[4] << 8 | res[5];
++
++	return val;
++}
++
++static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
++				  u16 val)
++{
++	int bus_addr, ret;
++	u8 buf[6];
++
++	if (!(reg & MII_ADDR_C45))
++		return -EOPNOTSUPP;
++
++	bus_addr = i2c_mii_phy_addr(phy_id);
++	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
++		return 0;
++
++	buf[0] = ROLLBALL_DATA_ADDR;
 +	buf[1] = (reg >> 16) & 0x1f;
 +	buf[2] = (reg >> 8) & 0xff;
 +	buf[3] = reg & 0xff;
@@ -317,7 +622,7 @@
  
  	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
  		return ERR_PTR(-EINVAL);
-@@ -104,10 +385,28 @@ struct mii_bus *mdio_i2c_alloc(struct de
+@@ -104,10 +385,28 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
  
  	snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent));
  	mii->parent = parent;
@@ -348,27 +653,11 @@
  	return mii;
  }
  EXPORT_SYMBOL_GPL(mdio_i2c_alloc);
---- a/include/linux/mdio/mdio-i2c.h
-+++ b/include/linux/mdio/mdio-i2c.h
-@@ -11,6 +11,14 @@ struct device;
- struct i2c_adapter;
- struct mii_bus;
- 
--struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
-+enum mdio_i2c_proto {
-+	MDIO_I2C_NONE,
-+	MDIO_I2C_MARVELL_C22,
-+	MDIO_I2C_C45,
-+	MDIO_I2C_ROLLBALL,
-+};
-+
-+struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
-+			       enum mdio_i2c_proto protocol);
- 
- #endif
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index f360d9225..67f34ed4c 100644
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
-@@ -483,62 +483,105 @@ static void phylink_resolve(struct work_
+@@ -483,62 +483,105 @@ static void phylink_resolve(struct work_struct *w)
  	struct phylink *pl = container_of(w, struct phylink, resolve);
  	struct phylink_link_state link_state;
  	struct net_device *ndev = pl->netdev;
@@ -498,6 +787,8 @@
  		mod_timer(&pl->link_poll, jiffies + HZ);
  	if (pl->phydev)
  		phy_start(pl->phydev);
+diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
+index a2f451c31..4be24406b 100644
 --- a/drivers/net/phy/sfp-bus.c
 +++ b/drivers/net/phy/sfp-bus.c
 @@ -10,12 +10,6 @@
@@ -601,7 +892,18 @@
  /**
   * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
   * @bus: a pointer to the &struct sfp_bus structure for the sfp module
-@@ -359,7 +272,7 @@ void sfp_parse_support(struct sfp_bus *b
+@@ -236,6 +149,10 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
+ 	unsigned int br_min, br_nom, br_max;
+ 	__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
+ 
++	phylink_set(modes, Autoneg);
++	phylink_set(modes, Pause);
++	phylink_set(modes, Asym_Pause);
++
+ 	/* Decode the bitrate information to MBd */
+ 	br_min = br_nom = br_max = 0;
+ 	if (id->base.br_nominal) {
+@@ -359,14 +276,10 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
  			phylink_set(modes, 1000baseX_Full);
  	}
  
@@ -610,6 +912,13 @@
  		bus->sfp_quirk->modes(id, modes);
  
  	bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
+-
+-	phylink_set(support, Autoneg);
+-	phylink_set(support, Pause);
+-	phylink_set(support, Asym_Pause);
+ }
+ EXPORT_SYMBOL_GPL(sfp_parse_support);
+ 
 @@ -737,12 +650,13 @@ void sfp_link_down(struct sfp_bus *bus)
  }
  EXPORT_SYMBOL_GPL(sfp_link_down);
@@ -626,9 +935,11 @@
  
  	if (ops && ops->module_insert)
  		ret = ops->module_insert(bus->upstream, id);
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index f8d1742e0..0fdf5d6d4 100644
 --- a/drivers/net/phy/sfp.c
 +++ b/drivers/net/phy/sfp.c
-@@ -165,6 +165,7 @@ static const enum gpiod_flags gpio_flags
+@@ -165,6 +165,7 @@ static const enum gpiod_flags gpio_flags[] = {
   * on board (for a copper SFP) time to initialise.
   */
  #define T_WAIT			msecs_to_jiffies(50)
@@ -636,7 +947,7 @@
  #define T_START_UP		msecs_to_jiffies(300)
  #define T_START_UP_BAD_GPON	msecs_to_jiffies(60000)
  
-@@ -204,8 +205,11 @@ static const enum gpiod_flags gpio_flags
+@@ -204,8 +205,11 @@ static const enum gpiod_flags gpio_flags[] = {
  
  /* SFP modules appear to always have their PHY configured for bus address
   * 0x56 (which with mdio-i2c, translates to a PHY address of 22).
@@ -676,7 +987,26 @@
  
  #if IS_ENABLED(CONFIG_HWMON)
  	struct sfp_diag diag;
-@@ -303,6 +313,156 @@ static const struct of_device_id sfp_of_
+@@ -287,6 +297,18 @@ static bool sfp_module_supported(const struct sfp_eeprom_id *id)
+ 	    !memcmp(id->base.vendor_pn, "UF-INSTANT      ", 16))
+ 		return true;
+ 
++	/* SFP GPON module SK-LiNK SFP-GE-LX20 SM1310 and SM1550 Instant
++	 * has in its EEPROM stored phys id UNK instead of SFP. Therefore
++	 * mark this module explicitly as supported based on vendor name
++	 * and pn match.
++	 */
++	if (id->base.phys_id == SFF8024_ID_UNK &&
++	    id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP &&
++	    !memcmp(id->base.vendor_name, "SK-LINK         ", 16) &&
++	    (!memcmp(id->base.vendor_pn, "SFP-GE-LX20-SM13", 16) ||
++	     !memcmp(id->base.vendor_pn, "SFP-GE-LX-SM1550", 16)))
++		return true;
++
+ 	return false;
+ }
+ 
+@@ -303,6 +325,180 @@ static const struct of_device_id sfp_of_match[] = {
  };
  MODULE_DEVICE_TABLE(of, sfp_of_match);
  
@@ -732,6 +1062,21 @@
 +	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, modes);
 +}
 +
++static void sfp_quirk_disable_autoneg(const struct sfp_eeprom_id *id,
++				      unsigned long *modes)
++{
++	linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, modes);
++}
++
++static void sfp_quirk_oem_2_5g(const struct sfp_eeprom_id *id,
++			       unsigned long *modes)
++{
++	/* Copper 2.5G SFP */
++	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, modes);
++	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
++	sfp_quirk_disable_autoneg(id, modes);
++}
++
 +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
 +				      unsigned long *modes)
 +{
@@ -773,10 +1118,19 @@
 +	// 2500MBd NRZ in their EEPROM
 +	SFP_QUIRK_M("Lantech", "8330-262D-E", '\0', sfp_quirk_2500basex),
 +
++	// CISCO PLRXPL-VC-S43-CG can operate at 10000baseSR, but not report
++	// in their EEPROM
 +	SFP_QUIRK_M("CISCO-JDSU", "PLRXPL-VC-S43-CG", '\0', sfp_quirk_10000baseSR),
 +
 +	SFP_QUIRK_M("UBNT", "UF-INSTANT", '\0', sfp_quirk_ubnt_uf_instant),
 +
++	// OEM SFP-2.5G-T can operate at 2500base-T, but not report
++	// in their EEPROM
++	SFP_QUIRK_M("OEM", "SFP-2.5G-T", '\0', sfp_quirk_oem_2_5g),
++	// TP-LINK TL-SM410U can operate at 2500base-T, but not report
++	// in their EEPROM
++	SFP_QUIRK_M("TP-LINK", "TL-SM410U", '\0', sfp_quirk_oem_2_5g),
++
 +	SFP_QUIRK_F("ETU", "ESP-T5-R", '\0', sfp_fixup_rollball_cc),
 +	SFP_QUIRK_F("OEM", "SFP-10G-T", '\0', sfp_fixup_rollball_cc),
 +	SFP_QUIRK_F("OEM", "RTSFP-10", '\0', sfp_fixup_rollball_cc),
@@ -833,7 +1187,7 @@
  static unsigned long poll_jiffies;
  
  static unsigned int sfp_gpio_get_state(struct sfp *sfp)
-@@ -414,9 +554,6 @@ static int sfp_i2c_write(struct sfp *sfp
+@@ -414,9 +610,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
  
  static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
  {
@@ -843,7 +1197,7 @@
  	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
  		return -EINVAL;
  
-@@ -424,7 +561,15 @@ static int sfp_i2c_configure(struct sfp
+@@ -424,7 +617,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
  	sfp->read = sfp_i2c_read;
  	sfp->write = sfp_i2c_write;
  
@@ -860,7 +1214,7 @@
  	if (IS_ERR(i2c_mii))
  		return PTR_ERR(i2c_mii);
  
-@@ -442,6 +587,12 @@ static int sfp_i2c_configure(struct sfp
+@@ -442,6 +643,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
  	return 0;
  }
  
@@ -873,7 +1227,7 @@
  /* Interface */
  static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
  {
-@@ -487,17 +638,18 @@ static void sfp_soft_set_state(struct sf
+@@ -487,17 +694,18 @@ static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
  static void sfp_soft_start_poll(struct sfp *sfp)
  {
  	const struct sfp_eeprom_id *id = &sfp->id;
@@ -901,7 +1255,7 @@
  
  	if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
  	    !sfp->need_poll)
-@@ -511,10 +663,11 @@ static void sfp_soft_stop_poll(struct sf
+@@ -511,10 +719,11 @@ static void sfp_soft_stop_poll(struct sfp *sfp)
  
  static unsigned int sfp_get_state(struct sfp *sfp)
  {
@@ -916,7 +1270,7 @@
  		state |= sfp_soft_get_state(sfp);
  
  	return state;
-@@ -1448,12 +1601,12 @@ static void sfp_sm_phy_detach(struct sfp
+@@ -1448,12 +1657,12 @@ static void sfp_sm_phy_detach(struct sfp *sfp)
  	sfp->mod_phy = NULL;
  }
  
@@ -931,7 +1285,7 @@
  	if (phy == ERR_PTR(-ENODEV))
  		return PTR_ERR(phy);
  	if (IS_ERR(phy)) {
-@@ -1548,6 +1701,14 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1548,6 +1757,14 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
  	}
  }
  
@@ -946,7 +1300,7 @@
  /* Probe a SFP for a PHY device if the module supports copper - the PHY
   * normally sits at I2C bus address 0x56, and may either be a clause 22
   * or clause 45 PHY.
-@@ -1563,19 +1724,23 @@ static int sfp_sm_probe_for_phy(struct s
+@@ -1563,36 +1780,52 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
  {
  	int err = 0;
  
@@ -979,7 +1333,6 @@
  	return err;
  }
  
-@@ -1755,17 +1783,29 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
  static int sfp_module_parse_power(struct sfp *sfp)
  {
  	u32 power_mW = 1000;
@@ -1014,7 +1367,7 @@
  			/* The module appears not to implement bus address
  			 * 0xa2, so assume that the module powers up in the
  			 * indicated mode.
-@@ -1782,13 +1822,21 @@ static int sfp_module_parse_power(struct sfp *sfp)
+@@ -1609,13 +1842,21 @@ static int sfp_module_parse_power(struct sfp *sfp)
  		}
  	}
  
@@ -1038,7 +1391,34 @@
  			 power_mW / 1000, (power_mW / 100) % 10);
  		return 0;
  	}
-@@ -1819,11 +1984,33 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1692,7 +1933,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
+ {
+ 	/* SFP module inserted - read I2C data */
+ 	struct sfp_eeprom_id id;
+-	bool cotsworks;
++	bool cotsworks, sklink;
+ 	u8 check;
+ 	int ret;
+ 
+@@ -1747,10 +1988,16 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
+ 	 */
+ 	cotsworks = !memcmp(id.base.vendor_name, "COTSWORKS       ", 16);
+ 
++	/* SK-LiNK do not seem to update the checksums when they
++	 * do the final programming with the final module part number,
++	 * serial number and date code.
++	 */
++	sklink = !memcmp(id.base.vendor_name, "SK-LINK         ", 16);
++
+ 	/* Validate the checksum over the base structure */
+ 	check = sfp_check(&id.base, sizeof(id.base) - 1);
+ 	if (check != id.base.cc_base) {
+-		if (cotsworks) {
++		if (cotsworks || sklink) {
+ 			dev_warn(sfp->dev,
+ 				 "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
+ 				 check, id.base.cc_base);
+@@ -1819,11 +2066,33 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
  	if (ret < 0)
  		return ret;
  
@@ -1076,7 +1456,7 @@
  
  	return 0;
  }
-@@ -1936,7 +2123,8 @@ static void sfp_sm_module(struct sfp *sf
+@@ -1936,7 +2205,8 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
  			break;
  
  		/* Report the module insertion to the upstream device */
@@ -1086,7 +1466,7 @@
  		if (err < 0) {
  			sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
  			break;
-@@ -1995,6 +2183,8 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1995,6 +2265,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
  			sfp_module_stop(sfp->sfp_bus);
  		if (sfp->mod_phy)
  			sfp_sm_phy_detach(sfp);
@@ -1095,7 +1475,7 @@
  		sfp_module_tx_disable(sfp);
  		sfp_soft_stop_poll(sfp);
  		sfp_sm_next(sfp, SFP_S_DOWN, 0);
-@@ -2018,9 +2208,10 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2018,9 +2290,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
  
  		/* We need to check the TX_FAULT state, which is not defined
  		 * while TX_DISABLE is asserted. The earliest we want to do
@@ -1108,7 +1488,7 @@
  		break;
  
  	case SFP_S_WAIT:
-@@ -2034,8 +2225,8 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2034,8 +2307,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
  			 * deasserting.
  			 */
  			timeout = sfp->module_t_start_up;
@@ -1119,7 +1499,7 @@
  			else
  				timeout = 1;
  
-@@ -2057,6 +2248,12 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2057,6 +2330,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
  				     sfp->sm_fault_retries == N_FAULT_INIT);
  		} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
  	init_done:
@@ -1132,7 +1512,7 @@
  			sfp->sm_phy_retries = R_PHY_RETRY;
  			goto phy_probe;
  		}
-@@ -2409,6 +2606,8 @@ static int sfp_probe(struct platform_dev
+@@ -2409,6 +2688,8 @@ static int sfp_probe(struct platform_device *pdev)
  				return PTR_ERR(sfp->gpio[i]);
  		}
  
@@ -1141,6 +1521,8 @@
  	sfp->get_state = sfp_gpio_get_state;
  	sfp->set_state = sfp_gpio_set_state;
  
+diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
+index b83f70526..f533e2dd6 100644
 --- a/drivers/net/phy/sfp.h
 +++ b/drivers/net/phy/sfp.h
 @@ -6,6 +6,14 @@
@@ -1158,7 +1540,7 @@
  struct sfp_socket_ops {
  	void (*attach)(struct sfp *sfp);
  	void (*detach)(struct sfp *sfp);
-@@ -20,7 +27,8 @@ int sfp_add_phy(struct sfp_bus *bus, str
+@@ -20,7 +28,8 @@ int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev);
  void sfp_remove_phy(struct sfp_bus *bus);
  void sfp_link_up(struct sfp_bus *bus);
  void sfp_link_down(struct sfp_bus *bus);
@@ -1168,274 +1550,26 @@
  void sfp_module_remove(struct sfp_bus *bus);
  int sfp_module_start(struct sfp_bus *bus);
  void sfp_module_stop(struct sfp_bus *bus);
---- a/drivers/net/phy/marvell10g.c
-+++ b/drivers/net/phy/marvell10g.c
-@@ -32,6 +32,15 @@
- #define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
- 
- enum {
-+	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
-+	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
-+	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
-+	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
-+	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
-+	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
-+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
-+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
-+	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
- 	MV_PMA_BOOT		= 0xc050,
- 	MV_PMA_BOOT_FATAL	= BIT(0),
- 
-@@ -53,7 +62,18 @@ enum {
- 
- 	/* Vendor2 MMD registers */
- 	MV_V2_PORT_CTRL		= 0xf001,
--	MV_V2_PORT_CTRL_PWRDOWN = 0x0800,
-+	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
-+	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
-+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
-+	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
-+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
-+	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
- 	MV_V2_TEMP_CTRL		= 0xf08a,
- 	MV_V2_TEMP_CTRL_MASK	= 0xc000,
- 	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
-@@ -62,11 +82,24 @@ enum {
- 	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
- };
- 
-+struct mv3310_chip {
-+	int (*get_mactype)(struct phy_device *phydev);
-+	int (*init_interface)(struct phy_device *phydev, int mactype);
-+};
-+
- struct mv3310_priv {
-+	bool rate_match;
-+	phy_interface_t const_interface;
-+
- 	struct device *hwmon_dev;
- 	char *hwmon_name;
- };
- 
-+static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
-+{
-+	return phydev->drv->driver_data;
-+}
-+
- #ifdef CONFIG_HWMON
- static umode_t mv3310_hwmon_is_visible(const void *data,
- 				       enum hwmon_sensor_types type,
-@@ -155,13 +188,6 @@ static int mv3310_hwmon_config(struct ph
- 			      MV_V2_TEMP_CTRL_MASK, val);
- }
- 
--static void mv3310_hwmon_disable(void *data)
--{
--	struct phy_device *phydev = data;
--
--	mv3310_hwmon_config(phydev, false);
--}
--
- static int mv3310_hwmon_probe(struct phy_device *phydev)
- {
- 	struct device *dev = &phydev->mdio.dev;
-@@ -185,10 +211,6 @@ static int mv3310_hwmon_probe(struct phy
- 	if (ret)
- 		return ret;
- 
--	ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
--	if (ret)
--		return ret;
--
- 	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
- 				priv->hwmon_name, phydev,
- 				&mv3310_hwmon_chip_info, NULL);
-@@ -262,6 +284,11 @@ static int mv3310_probe(struct phy_devic
- 	return phy_sfp_probe(phydev, &mv3310_sfp_ops);
- }
- 
-+static void mv3310_remove(struct phy_device *phydev)
-+{
-+	mv3310_hwmon_config(phydev, false);
-+}
-+
- static int mv3310_suspend(struct phy_device *phydev)
- {
- 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
-@@ -297,8 +324,84 @@ static bool mv3310_has_pma_ngbaset_quirk
- 		MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
- }
- 
-+static int mv2110_get_mactype(struct phy_device *phydev)
-+{
-+	int mactype;
-+
-+	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
-+	if (mactype < 0)
-+		return mactype;
-+
-+	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
-+}
-+
-+static int mv3310_get_mactype(struct phy_device *phydev)
-+{
-+	int mactype;
-+
-+	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
-+	if (mactype < 0)
-+		return mactype;
-+
-+	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
-+}
-+
-+static int mv2110_init_interface(struct phy_device *phydev, int mactype)
-+{
-+	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
-+
-+	priv->rate_match = false;
-+
-+	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
-+		priv->rate_match = true;
-+
-+	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII)
-+		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
-+	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
-+		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
-+	else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER ||
-+		 mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN)
-+		priv->const_interface = PHY_INTERFACE_MODE_NA;
-+	else
-+		return -EINVAL;
-+
-+	return 0;
-+}
-+
-+static int mv3310_init_interface(struct phy_device *phydev, int mactype)
-+{
-+	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
-+
-+	priv->rate_match = false;
-+
-+	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
-+	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
-+	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
-+		priv->rate_match = true;
-+
-+	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII)
-+		priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
-+	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
-+		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN ||
-+		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER)
-+		priv->const_interface = PHY_INTERFACE_MODE_10GKR;
-+	else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
-+		 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI)
-+		priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
-+	else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH ||
-+		 mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI)
-+		priv->const_interface = PHY_INTERFACE_MODE_XAUI;
-+	else
-+		return -EINVAL;
-+
-+	return 0;
-+}
-+
- static int mv3310_config_init(struct phy_device *phydev)
- {
-+	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
-+	int err, mactype;
-+
- 	/* Check that the PHY interface type is compatible */
- 	if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
- 	    phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
-@@ -307,6 +410,16 @@ static int mv3310_config_init(struct phy
- 	    phydev->interface != PHY_INTERFACE_MODE_10GKR)
- 		return -ENODEV;
- 
-+	mactype = chip->get_mactype(phydev);
-+	if (mactype < 0)
-+		return mactype;
-+
-+	err = chip->init_interface(phydev, mactype);
-+	if (err) {
-+		phydev_err(phydev, "MACTYPE configuration invalid\n");
-+		return err;
-+	}
-+
- 	return 0;
- }
- 
-@@ -384,6 +497,23 @@ static int mv3310_aneg_done(struct phy_d
- 
- static void mv3310_update_interface(struct phy_device *phydev)
- {
-+	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
-+
-+	if (!phydev->link)
-+		return;
-+
-+	/* In all of the "* with Rate Matching" modes the PHY interface is fixed
-+	 * at 10Gb. The PHY adapts the rate to actual wire speed with help of
-+	 * internal 16KB buffer.
-+	 *
-+	 * In USXGMII mode the PHY interface mode is also fixed.
-+	 */
-+	if (priv->rate_match ||
-+	    priv->const_interface == PHY_INTERFACE_MODE_USXGMII) {
-+		phydev->interface = priv->const_interface;
-+		return;
-+	}
-+
- 	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
- 	     phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
- 	     phydev->interface == PHY_INTERFACE_MODE_5GBASER ||
-@@ -503,11 +633,22 @@ static int mv3310_read_status(struct phy
- 	return 0;
- }
+diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
+index 751dab281..1c2114068 100644
+--- a/include/linux/mdio/mdio-i2c.h
++++ b/include/linux/mdio/mdio-i2c.h
+@@ -11,6 +11,14 @@ struct device;
+ struct i2c_adapter;
+ struct mii_bus;
  
-+static const struct mv3310_chip mv3310_type = {
-+	.get_mactype = mv3310_get_mactype,
-+	.init_interface = mv3310_init_interface,
-+};
-+
-+static const struct mv3310_chip mv2111_type = {
-+	.get_mactype = mv2110_get_mactype,
-+	.init_interface = mv2110_init_interface,
+-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
++enum mdio_i2c_proto {
++	MDIO_I2C_NONE,
++	MDIO_I2C_MARVELL_C22,
++	MDIO_I2C_C45,
++	MDIO_I2C_ROLLBALL,
 +};
 +
- static struct phy_driver mv3310_drivers[] = {
- 	{
- 		.phy_id		= MARVELL_PHY_ID_88X3310,
- 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
- 		.name		= "mv88x3310",
-+		.driver_data	= &mv3310_type,
- 		.get_features	= mv3310_get_features,
- 		.soft_reset	= genphy_no_soft_reset,
- 		.config_init	= mv3310_config_init,
-@@ -517,11 +658,13 @@ static struct phy_driver mv3310_drivers[
- 		.config_aneg	= mv3310_config_aneg,
- 		.aneg_done	= mv3310_aneg_done,
- 		.read_status	= mv3310_read_status,
-+		.remove		= mv3310_remove,
- 	},
- 	{
- 		.phy_id		= MARVELL_PHY_ID_88E2110,
- 		.phy_id_mask	= MARVELL_PHY_ID_MASK,
- 		.name		= "mv88x2110",
-+		.driver_data	= &mv2111_type,
- 		.probe		= mv3310_probe,
- 		.suspend	= mv3310_suspend,
- 		.resume		= mv3310_resume,
-@@ -530,6 +673,7 @@ static struct phy_driver mv3310_drivers[
- 		.config_aneg	= mv3310_config_aneg,
- 		.aneg_done	= mv3310_aneg_done,
- 		.read_status	= mv3310_read_status,
-+		.remove		= mv3310_remove,
- 	},
- };
++struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
++			       enum mdio_i2c_proto protocol);
  
+ #endif
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-net-phy-add-phylink-pcs-support.patch
similarity index 96%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-net-phy-add-phylink-pcs-support.patch
index 99e4141..8f298c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-net-phy-add-phylink-pcs-support.patch
@@ -1,5 +1,16 @@
+From 45878f8001b0ad75c5497a999a43b5901c1e03a6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:01 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1710-net-phy-add-phylink-pcs-support.patch]
+
+---
+ drivers/net/phy/phylink.c | 306 ++++++++++++++++++++++++++++++--------
+ include/linux/phylink.h   | 195 ++++++++++++++++++++++++
+ 2 files changed, 443 insertions(+), 58 deletions(-)
+
 diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
-index 67f34ed..ead9b37 100644
+index 67f34ed4c..9c76517ea 100644
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
 @@ -40,8 +40,9 @@ enum {
@@ -446,7 +457,7 @@
  
  	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
  	phylink_run_resolve(pl);
-@@ -1055,10 +1238,19 @@ void phylink_start(struct phylink *pl)
+@@ -1055,10 +1239,19 @@ void phylink_start(struct phylink *pl)
  				irq = 0;
  		}
  		if (irq <= 0)
@@ -469,7 +480,7 @@
  		mod_timer(&pl->link_poll, jiffies + HZ);
  	if (pl->phydev)
  		phy_start(pl->phydev);
-@@ -1202,7 +1394,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
+@@ -1202,7 +1395,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
  		if (pl->phydev)
  			break;
  
@@ -478,7 +489,7 @@
  
  		/* The MAC is reporting the link results from its own PCS
  		 * layer via in-band status. Report these as the current
-@@ -1314,7 +1506,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
+@@ -1314,7 +1507,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
  	if (pl->cur_link_an_mode == MLO_AN_INBAND &&
  	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
  		phylink_mac_config(pl, &pl->link_config);
@@ -487,7 +498,7 @@
  	}
  	mutex_unlock(&pl->state_mutex);
  
-@@ -1341,7 +1533,7 @@ int phylink_ethtool_nway_reset(struct phylink *pl)
+@@ -1341,7 +1534,7 @@ int phylink_ethtool_nway_reset(struct phylink *pl)
  
  	if (pl->phydev)
  		ret = phy_restart_aneg(pl->phydev);
@@ -496,7 +507,7 @@
  
  	return ret;
  }
-@@ -1410,7 +1602,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
+@@ -1410,7 +1603,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
  
  		case MLO_AN_INBAND:
  			phylink_mac_config(pl, config);
@@ -505,7 +516,7 @@
  			break;
  		}
  	}
-@@ -1621,10 +1813,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
+@@ -1621,10 +1814,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
  
  	case MLO_AN_INBAND:
  		if (phy_id == 0) {
@@ -517,7 +528,7 @@
  			val = phylink_mii_emul_read(reg, &state);
  		}
  		break;
-@@ -2010,7 +2010,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
+@@ -1820,7 +2010,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
  
  	if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
  				 &pl->phylink_disable_state))
@@ -527,7 +538,7 @@
  	return ret;
  }
 diff --git a/include/linux/phylink.h b/include/linux/phylink.h
-index 8229f56..ba0f09d 100644
+index 8229f56a1..ba0f09d02 100644
 --- a/include/linux/phylink.h
 +++ b/include/linux/phylink.h
 @@ -63,17 +63,23 @@ enum phylink_op_type {
@@ -782,3 +793,6 @@
  struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
  			       phy_interface_t iface,
  			       const struct phylink_mac_ops *ops);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/758-net-phy-add-phylink-pcs-decode-helper.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1711-net-phy-add-phylink-pcs-decode-helper.patch
similarity index 93%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/758-net-phy-add-phylink-pcs-decode-helper.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1711-net-phy-add-phylink-pcs-decode-helper.patch
index 164578a..1c7ff1c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/758-net-phy-add-phylink-pcs-decode-helper.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1711-net-phy-add-phylink-pcs-decode-helper.patch
@@ -1,5 +1,23 @@
+From 318f81610f630a026fd5ca0d4da7e34df25df663 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:02 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1711-net-phy-add-phylink-pcs-decode-helper.patch]
+
+---
+ drivers/net/phy/Makefile   |   3 +-
+ drivers/net/phy/linkmode.c |  95 +++++++++++++++++++
+ drivers/net/phy/phylink.c  | 188 +++++++++++++++++++++++++++++++++++++
+ include/linux/linkmode.h   |   6 ++
+ include/linux/mii.h        |  39 ++++++++
+ include/linux/phylink.h    |  30 ++++++
+ include/uapi/linux/mdio.h  |  26 +++++
+ include/uapi/linux/mii.h   |  17 ++++
+ 8 files changed, 403 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/phy/linkmode.c
+
 diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index 799ff9c..54ad7e8 100644
+index 8ea612a85..437ff2a2c 100644
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
 @@ -1,7 +1,8 @@
@@ -14,7 +32,7 @@
  ifdef CONFIG_MDIO_DEVICE
 diff --git a/drivers/net/phy/linkmode.c b/drivers/net/phy/linkmode.c
 new file mode 100644
-index 0000000..a5a347b
+index 000000000..a5a347bca
 --- /dev/null
 +++ b/drivers/net/phy/linkmode.c
 @@ -0,0 +1,95 @@
@@ -114,10 +132,10 @@
 +}
 +EXPORT_SYMBOL_GPL(linkmode_set_pause);
 diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
-index ead9b37..fec6d0e 100644
+index 9c76517ea..6b63b9839 100644
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
-@@ -2184,4 +2184,192 @@ void phylink_helper_basex_speed(struct phylink_link_state *state)
+@@ -2185,4 +2185,192 @@ void phylink_helper_basex_speed(struct phylink_link_state *state)
  }
  EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);
  
@@ -311,7 +329,7 @@
 +
  MODULE_LICENSE("GPL v2");
 diff --git a/include/linux/linkmode.h b/include/linux/linkmode.h
-index a99c588..d38da4e 100644
+index a99c58866..d38da4e89 100644
 --- a/include/linux/linkmode.h
 +++ b/include/linux/linkmode.h
 @@ -82,4 +82,10 @@ static inline int linkmode_equal(const unsigned long *src1,
@@ -326,7 +344,7 @@
 +
  #endif /* __LINKMODE_H */
 diff --git a/include/linux/mii.h b/include/linux/mii.h
-index 4ce8901..54b7f64 100644
+index 4ce8901a1..54b7f64b0 100644
 --- a/include/linux/mii.h
 +++ b/include/linux/mii.h
 @@ -485,6 +485,45 @@ static inline u32 linkmode_adv_to_lcl_adv_t(unsigned long *advertising)
@@ -376,7 +394,7 @@
   * mii_advertise_flowctrl - get flow control advertisement flags
   * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
 diff --git a/include/linux/phylink.h b/include/linux/phylink.h
-index ba0f09d..48ff9fe 100644
+index ba0f09d02..48ff9fead 100644
 --- a/include/linux/phylink.h
 +++ b/include/linux/phylink.h
 @@ -490,4 +490,34 @@ int phylink_mii_ioctl(struct phylink *, struct ifreq *, int);
@@ -415,7 +433,7 @@
 +				 uint16_t lpa);
  #endif
 diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
-index 4bcb41c..3f302e2 100644
+index 4bcb41c71..3f302e252 100644
 --- a/include/uapi/linux/mdio.h
 +++ b/include/uapi/linux/mdio.h
 @@ -324,4 +324,30 @@ static inline __u16 mdio_phy_id_c45(int prtad, int devad)
@@ -450,7 +468,7 @@
 +
  #endif /* _UAPI__LINUX_MDIO_H__ */
 diff --git a/include/uapi/linux/mii.h b/include/uapi/linux/mii.h
-index 51b48e4..90f9b4e 100644
+index 51b48e4be..90f9b4e1b 100644
 --- a/include/uapi/linux/mii.h
 +++ b/include/uapi/linux/mii.h
 @@ -131,6 +131,23 @@
@@ -477,3 +495,6 @@
  /* 1000BASE-T Control register */
  #define ADVERTISE_1000FULL	0x0200  /* Advertise 1000BASE-T full duplex */
  #define ADVERTISE_1000HALF	0x0100  /* Advertise 1000BASE-T half duplex */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1712-net-phy-add-phylink-rate-matching-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1712-net-phy-add-phylink-rate-matching-support.patch
new file mode 100644
index 0000000..3b9d2a6
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1712-net-phy-add-phylink-rate-matching-support.patch
@@ -0,0 +1,413 @@
+diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
+index 8406412..96d9e1f 100644
+--- a/drivers/net/phy/phy-core.c
++++ b/drivers/net/phy/phy-core.c
+@@ -62,6 +62,27 @@ const char *phy_duplex_to_str(unsigned int duplex)
+ }
+ EXPORT_SYMBOL_GPL(phy_duplex_to_str);
+ 
++/**
++ * phy_rate_matching_to_str - Return a string describing the rate matching
++ *
++ * @rate_matching: Type of rate matching to describe
++ */
++const char *phy_rate_matching_to_str(int rate_matching)
++{
++	switch (rate_matching) {
++	case RATE_MATCH_NONE:
++		return "none";
++	case RATE_MATCH_PAUSE:
++		return "pause";
++	case RATE_MATCH_CRS:
++		return "crs";
++	case RATE_MATCH_OPEN_LOOP:
++		return "open-loop";
++	}
++	return "Unsupported (update phy-core.c)";
++}
++EXPORT_SYMBOL_GPL(phy_rate_matching_to_str);
++
+ /* A mapping of all SUPPORTED settings to speed/duplex.  This table
+  * must be grouped by speed and sorted in descending match priority
+  * - iow, descending speed. */
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index e223f0d..6f2e4c7 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -106,6 +106,33 @@ void phy_print_status(struct phy_device *phydev)
+ }
+ EXPORT_SYMBOL(phy_print_status);
+ 
++/**
++ * phy_get_rate_matching - determine if rate matching is supported
++ * @phydev: The phy device to return rate matching for
++ * @iface: The interface mode to use
++ *
++ * This determines the type of rate matching (if any) that @phy supports
++ * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any
++ * interface supports rate matching.
++ *
++ * Return: The type of rate matching @phy supports for @iface, or
++ *         %RATE_MATCH_NONE.
++ */
++int phy_get_rate_matching(struct phy_device *phydev,
++			  phy_interface_t iface)
++{
++	int ret = RATE_MATCH_NONE;
++
++	if (phydev->drv->get_rate_matching) {
++		mutex_lock(&phydev->lock);
++		ret = phydev->drv->get_rate_matching(phydev, iface);
++		mutex_unlock(&phydev->lock);
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(phy_get_rate_matching);
++
+ /**
+  * phy_clear_interrupt - Ack the phy device's interrupt
+  * @phydev: the phy_device struct
+@@ -380,6 +407,7 @@ void phy_ethtool_ksettings_get(struct phy_device *phydev,
+ 
+ 	cmd->base.speed = phydev->speed;
+ 	cmd->base.duplex = phydev->duplex;
++	cmd->base.rate_matching = phydev->rate_matching;
+ 	if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
+ 		cmd->base.port = PORT_BNC;
+ 	else
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index 6b63b98..949e3b8 100644
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -155,6 +155,64 @@ static const char *phylink_an_mode_str(unsigned int mode)
+ 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
+ }
+ 
++/**
++ * phylink_interface_max_speed() - get the maximum speed of a phy interface
++ * @interface: phy interface mode defined by &typedef phy_interface_t
++ *
++ * Determine the maximum speed of a phy interface. This is intended to help
++ * determine the correct speed to pass to the MAC when the phy is performing
++ * rate matching.
++ *
++ * Return: The maximum speed of @interface
++ */
++static int phylink_interface_max_speed(phy_interface_t interface)
++{
++	switch (interface) {
++	case PHY_INTERFACE_MODE_RMII:
++	case PHY_INTERFACE_MODE_SMII:
++	case PHY_INTERFACE_MODE_REVMII:
++	case PHY_INTERFACE_MODE_MII:
++		return SPEED_100;
++
++	case PHY_INTERFACE_MODE_TBI:
++	case PHY_INTERFACE_MODE_MOCA:
++	case PHY_INTERFACE_MODE_RTBI:
++	case PHY_INTERFACE_MODE_1000BASEX:
++	case PHY_INTERFACE_MODE_TRGMII:
++	case PHY_INTERFACE_MODE_RGMII_TXID:
++	case PHY_INTERFACE_MODE_RGMII_RXID:
++	case PHY_INTERFACE_MODE_RGMII_ID:
++	case PHY_INTERFACE_MODE_RGMII:
++	case PHY_INTERFACE_MODE_QSGMII:
++	case PHY_INTERFACE_MODE_SGMII:
++	case PHY_INTERFACE_MODE_GMII:
++		return SPEED_1000;
++
++	case PHY_INTERFACE_MODE_2500BASEX:
++		return SPEED_2500;
++
++	case PHY_INTERFACE_MODE_5GBASER:
++		return SPEED_5000;
++
++	case PHY_INTERFACE_MODE_XGMII:
++	case PHY_INTERFACE_MODE_RXAUI:
++	case PHY_INTERFACE_MODE_XAUI:
++	case PHY_INTERFACE_MODE_10GKR:
++	case PHY_INTERFACE_MODE_USXGMII:
++		return SPEED_10000;
++
++	case PHY_INTERFACE_MODE_INTERNAL:
++	case PHY_INTERFACE_MODE_NA:
++	case PHY_INTERFACE_MODE_MAX:
++		/* No idea! Garbage in, unknown out */
++		return SPEED_UNKNOWN;
++	}
++
++	/* If we get here, someone forgot to add an interface mode above */
++	WARN_ON_ONCE(1);
++	return SPEED_UNKNOWN;
++}
++
+ static int phylink_validate_mac_and_pcs(struct phylink *pl,
+ 					unsigned long *supported,
+ 					struct phylink_link_state *state)
+@@ -402,11 +460,12 @@ static void phylink_mac_config(struct phylink *pl,
+ 			       const struct phylink_link_state *state)
+ {
+ 	phylink_dbg(pl,
+-		    "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
++		    "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
+ 		    __func__, phylink_an_mode_str(pl->cur_link_an_mode),
+ 		    phy_modes(state->interface),
+ 		    phy_speed_to_str(state->speed),
+ 		    phy_duplex_to_str(state->duplex),
++		    phy_rate_matching_to_str(state->rate_matching),
+ 		    __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
+ 		    state->pause, state->link, state->an_enabled);
+ 
+@@ -499,6 +558,7 @@ static void phylink_mac_pcs_get_state(struct phylink *pl,
+ 	linkmode_zero(state->lp_advertising);
+ 	state->interface = pl->link_config.interface;
+ 	state->an_enabled = pl->link_config.an_enabled;
++	state->rate_matching = pl->link_config.rate_matching;
+ 	if (state->an_enabled) {
+ 		state->speed = SPEED_UNKNOWN;
+ 		state->duplex = DUPLEX_UNKNOWN;
+@@ -614,9 +674,32 @@ static void phylink_link_up(struct phylink *pl,
+ {
+ 	struct net_device *ndev = pl->netdev;
+ 	int speed, duplex;
++	bool rx_pause;
+ 
+ 	speed = link_state.speed;
+ 	duplex = link_state.duplex;
++	rx_pause = !!(link_state.pause & MLO_PAUSE_RX);
++
++	switch (link_state.rate_matching) {
++	case RATE_MATCH_PAUSE:
++		/* The PHY is doing rate matchion from the media rate (in
++		 * the link_state) to the interface speed, and will send
++		 * pause frames to the MAC to limit its transmission speed.
++		 */
++		speed = phylink_interface_max_speed(link_state.interface);
++		duplex = DUPLEX_FULL;
++		rx_pause = true;
++		break;
++
++	case RATE_MATCH_CRS:
++		/* The PHY is doing rate matchion from the media rate (in
++		 * the link_state) to the interface speed, and will cause
++		 * collisions to the MAC to limit its transmission speed.
++		 */
++		speed = phylink_interface_max_speed(link_state.interface);
++		duplex = DUPLEX_HALF;
++		break;
++	}
+ 
+ 	pl->cur_interface = link_state.interface;
+ 
+@@ -626,8 +709,7 @@ static void phylink_link_up(struct phylink *pl,
+ 
+ 	pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
+ 				 pl->cur_interface, speed, duplex,
+-				 !!(link_state.pause & MLO_PAUSE_TX),
+-				 !!(link_state.pause & MLO_PAUSE_RX));
++				 !!(link_state.pause & MLO_PAUSE_TX), rx_pause);
+ 
+ 	if (ndev)
+ 		netif_carrier_on(ndev);
+@@ -719,6 +801,17 @@ static void phylink_resolve(struct work_struct *w)
+ 				}
+ 				link_state.interface = pl->phy_state.interface;
+ 
++				/* If we are doing rate matching, then the
++				 * link speed/duplex comes from the PHY
++				 */
++				if (pl->phy_state.rate_matching) {
++					link_state.rate_matching =
++						pl->phy_state.rate_matching;
++					link_state.speed = pl->phy_state.speed;
++					link_state.duplex =
++						pl->phy_state.duplex;
++				}
++
+ 				/* If we have a PHY, we need to update with
+ 				 * the PHY flow control bits.
+ 				 */
+@@ -935,6 +1028,7 @@ static void phylink_phy_change(struct phy_device *phydev, bool up,
+ 	mutex_lock(&pl->state_mutex);
+ 	pl->phy_state.speed = phydev->speed;
+ 	pl->phy_state.duplex = phydev->duplex;
++	pl->phy_state.rate_matching = phydev->rate_matching;
+ 	pl->phy_state.pause = MLO_PAUSE_NONE;
+ 	if (phydev->pause)
+ 		pl->phy_state.pause |= MLO_PAUSE_SYM;
+@@ -946,10 +1040,11 @@ static void phylink_phy_change(struct phy_device *phydev, bool up,
+ 
+ 	phylink_run_resolve(pl);
+ 
+-	phylink_dbg(pl, "phy link %s %s/%s/%s\n", up ? "up" : "down",
++	phylink_dbg(pl, "phy link %s %s/%s/%s/%s\n", up ? "up" : "down",
+ 		    phy_modes(phydev->interface),
+ 		    phy_speed_to_str(phydev->speed),
+-		    phy_duplex_to_str(phydev->duplex));
++		    phy_duplex_to_str(phydev->duplex),
++		    phy_rate_matching_to_str(phydev->rate_matching));
+ }
+ 
+ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
+@@ -971,6 +1066,12 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
+ 	memset(&config, 0, sizeof(config));
+ 	linkmode_copy(supported, phy->supported);
+ 	linkmode_copy(config.advertising, phy->advertising);
++
++	/* Check whether we would use rate matching for the proposed interface
++	 * mode.
++	 */
++	config.rate_matching = phy_get_rate_matching(phy, interface);
++
+ 	config.interface = interface;
+ 
+ 	ret = phylink_validate(pl, supported, &config);
+@@ -988,6 +1089,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
+ 	mutex_lock(&pl->state_mutex);
+ 	pl->phydev = phy;
+ 	pl->phy_state.interface = interface;
++	pl->phy_state.rate_matching = RATE_MATCH_NONE;
+ 	linkmode_copy(pl->supported, supported);
+ 	linkmode_copy(pl->link_config.advertising, config.advertising);
+ 
+@@ -1348,8 +1450,10 @@ static void phylink_get_ksettings(const struct phylink_link_state *state,
+ {
+ 	phylink_merge_link_mode(kset->link_modes.advertising, state->advertising);
+ 	linkmode_copy(kset->link_modes.lp_advertising, state->lp_advertising);
+-	kset->base.speed = state->speed;
+-	kset->base.duplex = state->duplex;
++	if (kset->base.rate_matching == RATE_MATCH_NONE) {
++		kset->base.speed = state->speed;
++		kset->base.duplex = state->duplex;
++	}
+ 	kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE :
+ 				AUTONEG_DISABLE;
+ }
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 4f2c105..df9fb90 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -423,6 +423,8 @@ struct phy_device {
+ 	/* Interrupts are enabled */
+ 	unsigned interrupts:1;
+ 
++	int rate_matching;
++
+ 	enum phy_state state;
+ 
+ 	u32 dev_flags;
+@@ -544,6 +546,18 @@ struct phy_driver {
+ 	 */
+ 	int (*get_features)(struct phy_device *phydev);
+ 
++	/**
++	 * @get_rate_matching: Get the supported type of rate matching for a
++	 * particular phy interface. This is used by phy consumers to determine
++	 * whether to advertise lower-speed modes for that interface. It is
++	 * assumed that if a rate matching mode is supported on an interface,
++	 * then that interface's rate can be adapted to all slower link speeds
++	 * supported by the phy. If the interface is not supported, this should
++	 * return %RATE_MATCH_NONE.
++	 */
++	int (*get_rate_matching)(struct phy_device *phydev,
++				   phy_interface_t iface);
++
+ 	/* PHY Power Management */
+ 	int (*suspend)(struct phy_device *phydev);
+ 	int (*resume)(struct phy_device *phydev);
+@@ -704,6 +718,7 @@ struct phy_fixup {
+ 
+ const char *phy_speed_to_str(int speed);
+ const char *phy_duplex_to_str(unsigned int duplex);
++const char *phy_rate_matching_to_str(int rate_matching);
+ 
+ /* A structure for mapping a particular speed and duplex
+  * combination to a particular SUPPORTED and ADVERTISED value
+@@ -1242,6 +1257,8 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
+ void phy_request_interrupt(struct phy_device *phydev);
+ void phy_free_interrupt(struct phy_device *phydev);
+ void phy_print_status(struct phy_device *phydev);
++int phy_get_rate_matching(struct phy_device *phydev,
++			    phy_interface_t iface);
+ int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
+ void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode);
+ void phy_advertise_supported(struct phy_device *phydev);
+diff --git a/include/linux/phylink.h b/include/linux/phylink.h
+index 48ff9fe..e1c022f 100644
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -38,6 +38,10 @@ static inline bool phylink_autoneg_inband(unsigned int mode)
+  * @speed: link speed, one of the SPEED_* constants.
+  * @duplex: link duplex mode, one of DUPLEX_* constants.
+  * @pause: link pause state, described by MLO_PAUSE_* constants.
++ * @rate_matching: rate matching being performed, one of the RATE_MATCH_*
++ *   constants. If rate matching is taking place, then the speed/duplex of
++ *   the medium link mode (@speed and @duplex) and the speed/duplex of the phy
++ *   interface mode (@interface) are different.
+  * @link: true if the link is up.
+  * @an_enabled: true if autonegotiation is enabled/desired.
+  * @an_complete: true if autonegotiation has completed.
+@@ -49,6 +53,7 @@ struct phylink_link_state {
+ 	int speed;
+ 	int duplex;
+ 	int pause;
++	int rate_matching;
+ 	unsigned int link:1;
+ 	unsigned int an_enabled:1;
+ 	unsigned int an_complete:1;
+diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
+index 8d465e5..ce41d2f 100644
+--- a/include/uapi/linux/ethtool.h
++++ b/include/uapi/linux/ethtool.h
+@@ -1643,6 +1643,20 @@ static inline int ethtool_validate_duplex(__u8 duplex)
+ 	return 0;
+ }
+ 
++/* These are used to throttle the rate of data on the phy interface when the
++ * native speed of the interface is higher than the link speed. These should
++ * not be used for phy interfaces which natively support multiple speeds (e.g.
++ * MII or SGMII).
++ */
++/* No rate matching performed. */
++#define RATE_MATCH_NONE		0
++/* The phy sends pause frames to throttle the MAC. */
++#define RATE_MATCH_PAUSE	1
++/* The phy asserts CRS to prevent the MAC from transmitting. */
++#define RATE_MATCH_CRS		2
++/* The MAC is programmed with a sufficiently-large IPG. */
++#define RATE_MATCH_OPEN_LOOP	3
++
+ /* Which connector port. */
+ #define PORT_TP			0x00
+ #define PORT_AUI		0x01
+@@ -1832,6 +1846,7 @@ enum ethtool_reset_flags {
+  *	autonegotiation; 0 if unknown or not applicable.  Read-only.
+  * @transceiver: Used to distinguish different possible PHY types,
+  *	reported consistently by PHYLIB.  Read-only.
++ * @rate_matching: Rate adaptation performed by the PHY
+  *
+  * If autonegotiation is disabled, the speed and @duplex represent the
+  * fixed link mode and are writable if the driver supports multiple
+@@ -1879,7 +1894,8 @@ struct ethtool_link_settings {
+ 	__u8	eth_tp_mdix_ctrl;
+ 	__s8	link_mode_masks_nwords;
+ 	__u8	transceiver;
+-	__u8	reserved1[3];
++	__u8	reserved1[2];
++	__u8	rate_matching;
+ 	__u32	reserved[7];
+ 	__u32	link_mode_masks[0];
+ 	/* layout of link_mode_masks fields:
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 9ae38c3..41a8b1d 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -656,6 +656,7 @@ static int ethtool_get_link_ksettings(struct net_device *dev,
+ 	link_ksettings.base.cmd = ETHTOOL_GLINKSETTINGS;
+ 	link_ksettings.base.link_mode_masks_nwords
+ 		= __ETHTOOL_LINK_MODE_MASK_NU32;
++	link_ksettings.base.rate_matching = RATE_MATCH_NONE;
+ 
+ 	return store_link_ksettings_for_user(useraddr, &link_ksettings);
+ }
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2000-show_model_name_in_cpuinfo_on_arm64.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2000-show_model_name_in_cpuinfo_on_arm64.patch
new file mode 100644
index 0000000..12ad322
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2000-show_model_name_in_cpuinfo_on_arm64.patch
@@ -0,0 +1,29 @@
+From 9fb8ad91c5e221d44089ca908311842d61c8f289 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:02 +0800
+Subject: [PATCH] 
+ [basic-part][999-2000-show_model_name_in_cpuinfo_on_arm64.patch]
+
+---
+ arch/arm64/kernel/cpuinfo.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
+index 90b35011a..4324f12a2 100644
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -139,9 +139,8 @@ static int c_show(struct seq_file *m, void *v)
+ 		 * "processor".  Give glibc what it expects.
+ 		 */
+ 		seq_printf(m, "processor\t: %d\n", i);
+-		if (compat)
+-			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+-				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
++		seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
++			   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
+ 
+ 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+ 			   loops_per_jiffy / (500000UL/HZ),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1023-kgdb-add-interrupt-control.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2001-kgdb-add-interrupt-control.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1023-kgdb-add-interrupt-control.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2001-kgdb-add-interrupt-control.patch
index e0ee954..7973173 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1023-kgdb-add-interrupt-control.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2001-kgdb-add-interrupt-control.patch
@@ -1,5 +1,14 @@
+From 766f65096433dde206cdfa19c2cd644be6beaf32 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:02 +0800
+Subject: [PATCH] [basic-part][999-2001-kgdb-add-interrupt-control.patch]
+
+---
+ arch/arm64/kernel/kgdb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
 diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
-index 1a157ca..258fe4b 100644
+index 1a157ca33..258fe4b38 100644
 --- a/arch/arm64/kernel/kgdb.c
 +++ b/arch/arm64/kernel/kgdb.c
 @@ -18,6 +18,10 @@
@@ -40,3 +49,6 @@
  	kgdb_handle_exception(0, SIGTRAP, 0, regs);
  	return DBG_HOOK_HANDLED;
  }
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-clk-mtk-add-mt7986-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2010-clk-mtk-add-mt7986-support.patch
similarity index 79%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-clk-mtk-add-mt7986-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2010-clk-mtk-add-mt7986-support.patch
index 930e88b..0708076 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-clk-mtk-add-mt7986-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2010-clk-mtk-add-mt7986-support.patch
@@ -1,11 +1,21 @@
+From cd39b20ca69be67d38a2366e64c496f157f12672 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:02 +0800
+Subject: [PATCH] [basic-part][999-2010-clk-mtk-add-mt7986-support.patch]
+
+---
+ drivers/clk/mediatek/Kconfig  | 9 +++++++++
+ drivers/clk/mediatek/Makefile | 2 ++
+ 2 files changed, 11 insertions(+)
+
 diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
-index 7efc361..5f11280 100644
+index 7efc3617b..1c48fe9f5 100644
 --- a/drivers/clk/mediatek/Kconfig
 +++ b/drivers/clk/mediatek/Kconfig
 @@ -258,6 +258,15 @@ config COMMON_CLK_MT7629_HIFSYS
  	  This driver supports MediaTek MT7629 HIFSYS clocks providing
  	  to PCI-E and USB.
-
+ 
 +config COMMON_CLK_MT7986
 +	bool "Clock driver for MediaTek MT7986"
 +	depends on ARCH_MEDIATEK || COMPILE_TEST
@@ -19,7 +29,7 @@
  	bool "Clock driver for MediaTek MT8135"
  	depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
 diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
-index 8cdb76a..8c392f4 100644
+index 8cdb76a5c..8c392f4ef 100644
 --- a/drivers/clk/mediatek/Makefile
 +++ b/drivers/clk/mediatek/Makefile
 @@ -39,6 +39,7 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
@@ -37,5 +47,5 @@
 +obj-y += clk-bringup.o
 \ No newline at end of file
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-clk-mtk-add-mt7981-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2011-clk-mtk-add-mt7981-support.patch
similarity index 75%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-clk-mtk-add-mt7981-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2011-clk-mtk-add-mt7981-support.patch
index 72f9e8a..7bf43f4 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-clk-mtk-add-mt7981-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2011-clk-mtk-add-mt7981-support.patch
@@ -1,5 +1,15 @@
+From 0c59e472d0ace19f00d06b4ccf5dba6a7831c001 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:03 +0800
+Subject: [PATCH] [basic-part][999-2011-clk-mtk-add-mt7981-support.patch]
+
+---
+ drivers/clk/mediatek/Kconfig  | 8 ++++++++
+ drivers/clk/mediatek/Makefile | 1 +
+ 2 files changed, 9 insertions(+)
+
 diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
-index 1c48fe9..23393d5 100644
+index 1c48fe9f5..23393d5ec 100644
 --- a/drivers/clk/mediatek/Kconfig
 +++ b/drivers/clk/mediatek/Kconfig
 @@ -267,6 +267,14 @@ config COMMON_CLK_MT7986
@@ -18,7 +28,7 @@
  	bool "Clock driver for MediaTek MT8135"
  	depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
 diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
-index 8c392f4..ffe0850 100644
+index 8c392f4ef..ffe0850e1 100644
 --- a/drivers/clk/mediatek/Makefile
 +++ b/drivers/clk/mediatek/Makefile
 @@ -40,6 +40,7 @@ obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o
@@ -30,5 +40,5 @@
  obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
  obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2012-clk-mtk-add-mt7988-support.patch
similarity index 78%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2012-clk-mtk-add-mt7988-support.patch
index e673148..d29a023 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2012-clk-mtk-add-mt7988-support.patch
@@ -1,5 +1,15 @@
+From 63786d6f950d63c586b4efac77d3244b959ba5a6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:03 +0800
+Subject: [PATCH] [basic-part][999-2012-clk-mtk-add-mt7988-support.patch]
+
+---
+ drivers/clk/mediatek/Kconfig  | 8 ++++++++
+ drivers/clk/mediatek/Makefile | 3 ++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
 diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
-index 23393d5..cf3a53e 100644
+index 23393d5ec..cf3a53e9b 100644
 --- a/drivers/clk/mediatek/Kconfig
 +++ b/drivers/clk/mediatek/Kconfig
 @@ -275,6 +275,14 @@ config COMMON_CLK_MT7981
@@ -18,7 +28,7 @@
  	bool "Clock driver for MediaTek MT8135"
  	depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
 diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
-index ffe0850..43ca85d 100644
+index ffe0850e1..43ca85d10 100644
 --- a/drivers/clk/mediatek/Makefile
 +++ b/drivers/clk/mediatek/Makefile
 @@ -41,6 +41,7 @@ obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
@@ -36,3 +46,6 @@
 -obj-y += clk-bringup.o
 \ No newline at end of file
 +obj-y += clk-bringup.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2013-clk-mtk-add-chg-shift-control.patch
similarity index 69%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2013-clk-mtk-add-chg-shift-control.patch
index 4a9ff6f..7853f41 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2013-clk-mtk-add-chg-shift-control.patch
@@ -1,5 +1,15 @@
+From e640a8767e5ab047b8a4c89041ee3872132ce38a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:03 +0800
+Subject: [PATCH] [basic-part][999-2013-clk-mtk-add-chg-shift-control.patch]
+
+---
+ drivers/clk/mediatek/clk-mtk.h | 1 +
+ drivers/clk/mediatek/clk-pll.c | 5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
 diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
-index c3d6756..d84c45d 100644
+index c3d6756b0..d84c45d75 100644
 --- a/drivers/clk/mediatek/clk-mtk.h
 +++ b/drivers/clk/mediatek/clk-mtk.h
 @@ -231,6 +231,7 @@ struct mtk_pll_data {
@@ -11,7 +21,7 @@
  	const char *parent_name;
  };
 diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
-index f440f2c..db318fe 100644
+index f440f2cd0..db318fe1c 100644
 --- a/drivers/clk/mediatek/clk-pll.c
 +++ b/drivers/clk/mediatek/clk-pll.c
 @@ -136,7 +136,10 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
@@ -26,3 +36,6 @@
  	writel(chg, pll->pcw_chg_addr);
  	if (pll->tuner_addr)
  		writel(val + 1, pll->tuner_addr);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-add-mt7986-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2020-pinctrl-add-mt7986-driver.patch
similarity index 72%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-add-mt7986-driver.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2020-pinctrl-add-mt7986-driver.patch
index a02873d..ba9e2bb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-add-mt7986-driver.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2020-pinctrl-add-mt7986-driver.patch
@@ -1,5 +1,15 @@
+From 1cbd50ca51ad80b9c2527c1aaccb57b92dd6d635 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:03 +0800
+Subject: [PATCH] [basic-part][999-2020-pinctrl-add-mt7986-driver.patch]
+
+---
+ drivers/pinctrl/mediatek/Kconfig  | 7 +++++++
+ drivers/pinctrl/mediatek/Makefile | 1 +
+ 2 files changed, 8 insertions(+)
+
 diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
-index 701f9af..9109f91 100644
+index 701f9af63..9109f911a 100644
 --- a/drivers/pinctrl/mediatek/Kconfig
 +++ b/drivers/pinctrl/mediatek/Kconfig
 @@ -100,6 +100,13 @@ config PINCTRL_MT7622
@@ -17,7 +27,7 @@
  	bool "Mediatek MT8173 pin control"
  	depends on OF
 diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
-index a74325a..d408585 100644
+index a74325abd..d4085859a 100644
 --- a/drivers/pinctrl/mediatek/Makefile
 +++ b/drivers/pinctrl/mediatek/Makefile
 @@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_MT6797)	+= pinctrl-mt6797.o
@@ -28,3 +38,6 @@
  obj-$(CONFIG_PINCTRL_MT8173)	+= pinctrl-mt8173.o
  obj-$(CONFIG_PINCTRL_MT8183)	+= pinctrl-mt8183.o
  obj-$(CONFIG_PINCTRL_MT8516)	+= pinctrl-mt8516.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2021-pinctrl-enable-mt7988-pinctrl-config.patch
similarity index 62%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2021-pinctrl-enable-mt7988-pinctrl-config.patch
index 01f01f6..84f0b84 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2021-pinctrl-enable-mt7988-pinctrl-config.patch
@@ -1,8 +1,19 @@
+From c0566aeb32196514614c335efb3e280595da99c3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:04 +0800
+Subject: [PATCH] 
+ [basic-part][999-2021-pinctrl-enable-mt7988-pinctrl-config.patch]
+
+---
+ drivers/pinctrl/mediatek/Kconfig  | 7 +++++++
+ drivers/pinctrl/mediatek/Makefile | 1 +
+ 2 files changed, 8 insertions(+)
+
 diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
-index e7ec276..b6341dd 100644
+index 9109f911a..a2223dbe0 100644
 --- a/drivers/pinctrl/mediatek/Kconfig
 +++ b/drivers/pinctrl/mediatek/Kconfig
-@@ -112,6 +112,13 @@ config PINCTRL_MT7986
+@@ -107,6 +107,13 @@ config PINCTRL_MT7986
  	default ARM64 && ARCH_MEDIATEK
  	select PINCTRL_MTK_MOORE
  
@@ -17,14 +28,17 @@
  	bool "Mediatek MT8173 pin control"
  	depends on OF
 diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
-index e6813cf..6e28df9 100644
+index d4085859a..6526efc2c 100644
 --- a/drivers/pinctrl/mediatek/Makefile
 +++ b/drivers/pinctrl/mediatek/Makefile
-@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT7623)	+= pinctrl-mt7623.o
+@@ -16,6 +16,7 @@ obj-$(CONFIG_PINCTRL_MT7622)	+= pinctrl-mt7622.o
+ obj-$(CONFIG_PINCTRL_MT7623)	+= pinctrl-mt7623.o
  obj-$(CONFIG_PINCTRL_MT7629)	+= pinctrl-mt7629.o
- obj-$(CONFIG_PINCTRL_MT7981)	+= pinctrl-mt7981.o
  obj-$(CONFIG_PINCTRL_MT7986)	+= pinctrl-mt7986.o
 +obj-$(CONFIG_PINCTRL_MT7988)    += pinctrl-mt7988.o
  obj-$(CONFIG_PINCTRL_MT8173)	+= pinctrl-mt8173.o
  obj-$(CONFIG_PINCTRL_MT8183)	+= pinctrl-mt8183.o
  obj-$(CONFIG_PINCTRL_MT8516)	+= pinctrl-mt8516.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/402-pinctrl-add-mt7981-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2022-pinctrl-add-mt7981-driver.patch
similarity index 74%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/402-pinctrl-add-mt7981-driver.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2022-pinctrl-add-mt7981-driver.patch
index 9e67ee7..10f0938 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/402-pinctrl-add-mt7981-driver.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2022-pinctrl-add-mt7981-driver.patch
@@ -1,15 +1,15 @@
-From 1b529849f324edec053a34292e3f874bde8f7401 Mon Sep 17 00:00:00 2001
+From af29af4ab3fb39d3884ea9f7352e672c89093c3b Mon Sep 17 00:00:00 2001
 From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 25 Jun 2021 15:43:55 +0800
-Subject: [PATCH] Add mt7981 pinctrl driver support
+Date: Fri, 2 Jun 2023 13:06:04 +0800
+Subject: [PATCH] [basic-part][999-2022-pinctrl-add-mt7981-driver.patch]
 
 ---
- drivers/pinctrl/mediatek/Kconfig  | 7 +++++++
+ drivers/pinctrl/mediatek/Kconfig  | 5 +++++
  drivers/pinctrl/mediatek/Makefile | 1 +
- 2 files changed, 8 insertions(+)
+ 2 files changed, 6 insertions(+)
 
 diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
-index 9109f91..d40aee5 100644
+index a2223dbe0..b6341dd83 100644
 --- a/drivers/pinctrl/mediatek/Kconfig
 +++ b/drivers/pinctrl/mediatek/Kconfig
 @@ -100,6 +100,11 @@ config PINCTRL_MT7622
@@ -25,7 +25,7 @@
  	bool "Mediatek MT7986 pin control"
  	depends on OF
 diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
-index d408585..e6813cf 100644
+index 6526efc2c..b80ef66da 100644
 --- a/drivers/pinctrl/mediatek/Makefile
 +++ b/drivers/pinctrl/mediatek/Makefile
 @@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_MT6797)	+= pinctrl-mt6797.o
@@ -34,8 +34,8 @@
  obj-$(CONFIG_PINCTRL_MT7629)	+= pinctrl-mt7629.o
 +obj-$(CONFIG_PINCTRL_MT7981)	+= pinctrl-mt7981.o
  obj-$(CONFIG_PINCTRL_MT7986)	+= pinctrl-mt7986.o
+ obj-$(CONFIG_PINCTRL_MT7988)    += pinctrl-mt7988.o
  obj-$(CONFIG_PINCTRL_MT8173)	+= pinctrl-mt8173.o
- obj-$(CONFIG_PINCTRL_MT8183)	+= pinctrl-mt8183.o
 -- 
-2.6.4
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2040-powerdomain-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2040-powerdomain-add-mt7988-support.patch
new file mode 100644
index 0000000..33f4ae6
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2040-powerdomain-add-mt7988-support.patch
@@ -0,0 +1,21 @@
+From c04a931b0f3f8c1af74197ef22a9cbcb96697c9f Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:04 +0800
+Subject: [PATCH] [basic-part][999-2040-powerdomain-add-mt7988-support.patch]
+
+---
+ drivers/soc/mediatek/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index b01733074..1c485e3ba 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -3,3 +3,4 @@ obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
+ obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
+ obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
++obj-$(CONFIG_MTK_SCPSYS) += mtk-pm-domains.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0960-watchdog-add-mt7986-assert.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2050-watchdog-add-mt7986-assert.patch
similarity index 95%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0960-watchdog-add-mt7986-assert.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2050-watchdog-add-mt7986-assert.patch
index 619fc10..2b0f938 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0960-watchdog-add-mt7986-assert.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2050-watchdog-add-mt7986-assert.patch
@@ -1,5 +1,14 @@
+From d02a2cf00764f83a9efdc08685381ee9167b0a9e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:04 +0800
+Subject: [PATCH] [basic-part][999-2050-watchdog-add-mt7986-assert.patch]
+
+---
+ drivers/watchdog/mtk_wdt.c | 202 +++++++++++++++++++++++++++++++++++--
+ 1 file changed, 193 insertions(+), 9 deletions(-)
+
 diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
-index 9c3d003..30127d1 100644
+index 9c3d00332..30127d1e7 100644
 --- a/drivers/watchdog/mtk_wdt.c
 +++ b/drivers/watchdog/mtk_wdt.c
 @@ -9,6 +9,8 @@
@@ -326,3 +335,6 @@
 -MODULE_VERSION(DRV_VERSION);
 +MODULE_VERSION(DRV_VERSION);
 \ No newline at end of file
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0111-mt7986-trng-add-rng-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2100-mt7986-trng-add-rng-support.patch
similarity index 68%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0111-mt7986-trng-add-rng-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2100-mt7986-trng-add-rng-support.patch
index 1b132a3..bef2e1c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0111-mt7986-trng-add-rng-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2100-mt7986-trng-add-rng-support.patch
@@ -1,18 +1,14 @@
-From 6d4a858d6f7db2a86f6513a543feb8f7b8a8b4c1 Mon Sep 17 00:00:00 2001
-From: "Mingming.Su" <Mingming.Su@mediatek.com>
-Date: Wed, 30 Jun 2021 16:59:32 +0800
-Subject: [PATCH] mt7986: trng: add rng support
+From 28b23dd56546943c99dc4e884576e629b417fb6d Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:05 +0800
+Subject: [PATCH] [slow-speed-io][999-2100-mt7986-trng-add-rng-support.patch]
 
-1. Add trng compatible name for MT7986
-2. Fix mtk_rng_wait_ready() function
-
-Signed-off-by: Mingming.Su <Mingming.Su@mediatek.com>
 ---
  drivers/char/hw_random/mtk-rng.c | 5 +++--
  1 file changed, 3 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
-index e649be5a5..496adb0a0 100644
+index 6670516fa..a8bd06da7 100644
 --- a/drivers/char/hw_random/mtk-rng.c
 +++ b/drivers/char/hw_random/mtk-rng.c
 @@ -22,7 +22,7 @@
@@ -33,7 +29,7 @@
  }
  
  static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
-@@ -181,6 +181,7 @@ static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend,
+@@ -186,6 +186,7 @@ static const struct dev_pm_ops mtk_rng_pm_ops = {
  #endif	/* CONFIG_PM */
  
  static const struct of_device_id mtk_rng_match[] = {
@@ -42,5 +38,5 @@
  	{},
  };
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2101-Add-trngv2-driver-support.patch
similarity index 95%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2101-Add-trngv2-driver-support.patch
index 7c09a71..2169d20 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2101-Add-trngv2-driver-support.patch
@@ -1,7 +1,7 @@
-From ae5611b1b7a857edb3d9c8e900b550c76f7c236e Mon Sep 17 00:00:00 2001
-From: "Mingming.Su" <Mingming.Su@mediatek.com>
-Date: Fri, 17 Dec 2021 20:27:34 +0800
-Subject: [PATCH] Add trngv2 driver support
+From cff177b10455d17fec2c2a412a4f5491af3be315 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:05 +0800
+Subject: [PATCH] [slow-speed-io][999-2101-Add-trngv2-driver-support.patch]
 
 ---
  drivers/char/hw_random/mtk-rng.c | 105 +++++++++++++++++++++++--------
@@ -181,5 +181,5 @@
  };
  MODULE_DEVICE_TABLE(of, mtk_rng_match);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2102-trng-Add-trng-support-for-mt7988.patch
similarity index 77%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2102-trng-Add-trng-support-for-mt7988.patch
index a8f1dfe..80d3df8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2102-trng-Add-trng-support-for-mt7988.patch
@@ -1,11 +1,9 @@
-From cbd37bfc8221c1a81d235ddfb1898536a821c650 Mon Sep 17 00:00:00 2001
-From: "mingming.su" <Mingming.Su@mediatek.com>
-Date: Wed, 7 Sep 2022 15:44:46 +0800
-Subject: [PATCH] trng: Add trng support for mt7988
+From a63382c6164e5c856057a394f53c91cb0d79222f Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:05 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2102-trng-Add-trng-support-for-mt7988.patch]
 
-Add trng support for mt7988.
-
-Signed-off-by: mingming.su <Mingming.Su@mediatek.com>
 ---
  drivers/char/hw_random/mtk-rng.c | 5 +++++
  1 file changed, 5 insertions(+)
@@ -34,5 +32,5 @@
  	{},
  };
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2103-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
similarity index 74%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2103-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
index 5635f55..47ac32a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2103-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
@@ -1,19 +1,20 @@
-From 6110010f7b88392a3094f2aaec91ee54151cde2a Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:43:02 +0800
-Subject: [PATCH] drivers: char: tpm: Add calibration example for SPI TPM
- module
+From daaf90f34aa73625585f56d766e51c7b718bebc3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:05 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2103-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
  drivers/char/tpm/tpm_tis_core.c | 19 +++++++++++++++++++
  drivers/char/tpm/tpm_tis_core.h |  2 ++
  drivers/char/tpm/tpm_tis_spi.c  |  7 +++++++
  3 files changed, 28 insertions(+)
 
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index 70f785994..b9898a56d 100644
 --- a/drivers/char/tpm/tpm_tis_core.c
 +++ b/drivers/char/tpm/tpm_tis_core.c
-@@ -817,6 +817,21 @@ static const struct tpm_class_ops tpm_ti
+@@ -817,6 +817,21 @@ static const struct tpm_class_ops tpm_tis = {
  	.clk_enable = tpm_tis_clkrun_enable,
  };
  
@@ -35,7 +36,7 @@
  int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
  		      const struct tpm_tis_phy_ops *phy_ops,
  		      acpi_handle acpi_dev_handle)
-@@ -864,6 +879,10 @@ int tpm_tis_core_init(struct device *dev
+@@ -864,6 +879,10 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
  	if (chip->ops->clk_enable != NULL)
  		chip->ops->clk_enable(chip, true);
  
@@ -46,6 +47,8 @@
  	if (wait_startup(chip, 0) != 0) {
  		rc = -ENODEV;
  		goto out_err;
+diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
+index 7337819f5..7bb0bc8b6 100644
 --- a/drivers/char/tpm/tpm_tis_core.h
 +++ b/drivers/char/tpm/tpm_tis_core.h
 @@ -106,6 +106,7 @@ struct tpm_tis_phy_ops {
@@ -64,9 +67,11 @@
  int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
  		      const struct tpm_tis_phy_ops *phy_ops,
  		      acpi_handle acpi_dev_handle);
+diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
+index 19513e622..3be2d53a5 100644
 --- a/drivers/char/tpm/tpm_tis_spi.c
 +++ b/drivers/char/tpm/tpm_tis_spi.c
-@@ -184,12 +184,19 @@ static int tpm_tis_spi_write32(struct tp
+@@ -184,12 +184,19 @@ static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
  	return rc;
  }
  
@@ -86,3 +91,6 @@
  };
  
  static int tpm_tis_spi_probe(struct spi_device *dev)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0900-i2c-busses-add-mt7986-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2110-i2c-busses-add-mt7986-support.patch
similarity index 75%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0900-i2c-busses-add-mt7986-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2110-i2c-busses-add-mt7986-support.patch
index a375842..e97ff9b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0900-i2c-busses-add-mt7986-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2110-i2c-busses-add-mt7986-support.patch
@@ -1,11 +1,20 @@
+From 64902a41254881d559a2f1e4d2966f16e4a7f98a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:06 +0800
+Subject: [PATCH] [slow-speed-io][999-2110-i2c-busses-add-mt7986-support.patch]
+
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
 diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
-index e1ef012..4fd4721 100644
+index 5587e7c54..14d96c876 100644
 --- a/drivers/i2c/busses/i2c-mt65xx.c
 +++ b/drivers/i2c/busses/i2c-mt65xx.c
 @@ -289,6 +289,19 @@ static const struct mtk_i2c_compatible mt7622_compat = {
  	.ltiming_adjust = 0,
  };
-
+ 
 +static const struct mtk_i2c_compatible mt7986_compat = {
 +	.quirks = &mt7622_i2c_quirks,
 +	.regs = mt_i2c_regs_v1,
@@ -30,3 +39,6 @@
  	{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
  	{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
  	{}
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0901-i2c-busses-add-mt7981-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2111-i2c-busses-add-mt7981-support.patch
similarity index 79%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0901-i2c-busses-add-mt7981-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2111-i2c-busses-add-mt7981-support.patch
index f79d2f8..ba37f4a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0901-i2c-busses-add-mt7981-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2111-i2c-busses-add-mt7981-support.patch
@@ -1,5 +1,14 @@
+From c4ad4b0aa7fb10beb510b99caba9cd027a88a723 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:06 +0800
+Subject: [PATCH] [slow-speed-io][999-2111-i2c-busses-add-mt7981-support.patch]
+
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
 diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
-index e1ef012..4fd4721 100644
+index 14d96c876..995e8bbaf 100644
 --- a/drivers/i2c/busses/i2c-mt65xx.c
 +++ b/drivers/i2c/busses/i2c-mt65xx.c
 @@ -157,7 +157,7 @@ static const u16 mt_i2c_regs_v1[] = {
@@ -39,5 +48,5 @@
  	{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
  	{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/500-auxadc-add-auxadc-32k-clk.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2120-auxadc-add-auxadc-32k-clk.patch
similarity index 73%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/500-auxadc-add-auxadc-32k-clk.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2120-auxadc-add-auxadc-32k-clk.patch
index dc0dd2f..2125916 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/500-auxadc-add-auxadc-32k-clk.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2120-auxadc-add-auxadc-32k-clk.patch
@@ -1,5 +1,14 @@
+From ab1b6a5a856d2ade01ce7f677dc8943ffc476c35 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:06 +0800
+Subject: [PATCH] [slow-speed-io][999-2120-auxadc-add-auxadc-32k-clk.patch]
+
+---
+ drivers/iio/adc/mt6577_auxadc.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
 diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c
-index 2449d91..b8a43eb 100644
+index 9cdb9084c..34f94554f 100644
 --- a/drivers/iio/adc/mt6577_auxadc.c
 +++ b/drivers/iio/adc/mt6577_auxadc.c
 @@ -42,6 +42,7 @@ struct mtk_auxadc_compatible {
@@ -10,7 +19,7 @@
  	struct mutex lock;
  	const struct mtk_auxadc_compatible *dev_comp;
  };
-@@ -214,6 +215,12 @@ static int __maybe_unused mt6577_auxadc_resume(struct device *dev)
+@@ -222,6 +223,12 @@ static int __maybe_unused mt6577_auxadc_resume(struct device *dev)
  		return ret;
  	}
  
@@ -23,7 +32,7 @@
  	mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  			      MT6577_AUXADC_PDN_EN, 0);
  	mdelay(MT6577_AUXADC_POWER_READY_MS);
-@@ -228,6 +235,8 @@ static int __maybe_unused mt6577_auxadc_suspend(struct device *dev)
+@@ -236,6 +243,8 @@ static int __maybe_unused mt6577_auxadc_suspend(struct device *dev)
  
  	mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  			      0, MT6577_AUXADC_PDN_EN);
@@ -32,7 +41,7 @@
  	clk_disable_unprepare(adc_dev->adc_clk);
  
  	return 0;
-@@ -272,6 +281,17 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
+@@ -280,6 +289,17 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
  		return ret;
  	}
  
@@ -50,7 +59,7 @@
  	adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
  	if (!adc_clk_rate) {
  		ret = -EINVAL;
-@@ -301,6 +321,7 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
+@@ -309,6 +329,7 @@ err_power_off:
  	mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  			      0, MT6577_AUXADC_PDN_EN);
  err_disable_clk:
@@ -58,7 +67,7 @@
  	clk_disable_unprepare(adc_dev->adc_clk);
  	return ret;
  }
-@@ -315,6 +336,7 @@ static int mt6577_auxadc_remove(struct platform_device *pdev)
+@@ -323,6 +344,7 @@ static int mt6577_auxadc_remove(struct platform_device *pdev)
  	mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  			      0, MT6577_AUXADC_PDN_EN);
  
@@ -66,3 +75,6 @@
  	clk_disable_unprepare(adc_dev->adc_clk);
  
  	return 0;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0930-pwm-add-mt7986-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2130-pwm-add-mt7986-support.patch
similarity index 72%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0930-pwm-add-mt7986-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2130-pwm-add-mt7986-support.patch
index a791d3a..dac5409 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0930-pwm-add-mt7986-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2130-pwm-add-mt7986-support.patch
@@ -1,11 +1,20 @@
+From dcce03b49e8bac8a2c371c24dbcc9a6922861b8a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:07 +0800
+Subject: [PATCH] [slow-speed-io][999-2130-pwm-add-mt7986-support.patch]
+
+---
+ drivers/pwm/pwm-mediatek.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
 diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
-index b94e0d0..35a0db2 100644
+index b94e0d09c..35a0db2ff 100644
 --- a/drivers/pwm/pwm-mediatek.c
 +++ b/drivers/pwm/pwm-mediatek.c
 @@ -302,6 +302,11 @@ static const struct pwm_mediatek_of_data mt7629_pwm_data = {
  	.pwm45_fixup = false,
  };
-
+ 
 +static const struct pwm_mediatek_of_data mt7986_pwm_data = {
 +	.num_pwms = 2,
 +	.pwm45_fixup = false,
@@ -22,3 +31,6 @@
  	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
  	{ },
  };
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0931-pwm-add-mt7981-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2131-pwm-add-mt7981-support.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0931-pwm-add-mt7981-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2131-pwm-add-mt7981-support.patch
index 0de7966..e137dc4 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0931-pwm-add-mt7981-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2131-pwm-add-mt7981-support.patch
@@ -1,8 +1,17 @@
+From c6dc9128df3673041cade417331ad2579e669520 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:07 +0800
+Subject: [PATCH] [slow-speed-io][999-2131-pwm-add-mt7981-support.patch]
+
+---
+ drivers/pwm/pwm-mediatek.c | 51 +++++++++++++++++++++++++++++++++++---
+ 1 file changed, 48 insertions(+), 3 deletions(-)
+
 diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
-index 7c56ee2..3a5a456 100644
+index 35a0db2ff..f4393bd46 100644
 --- a/drivers/pwm/pwm-mediatek.c
 +++ b/drivers/pwm/pwm-mediatek.c
-@@ -33,10 +32,13 @@
+@@ -32,10 +32,13 @@
  #define PWM45THRES_FIXUP	0x34
  
  #define PWM_CLK_DIV_MAX		7
@@ -16,7 +25,7 @@
  };
  
  /**
-@@ -57,10 +59,14 @@ struct pwm_mediatek_chip {
+@@ -56,10 +59,14 @@ struct pwm_mediatek_chip {
  	const struct pwm_mediatek_of_data *soc;
  };
  
@@ -32,7 +41,7 @@
  static inline struct pwm_mediatek_chip *
  to_pwm_mediatek_chip(struct pwm_chip *chip)
  {
-@@ -108,14 +114,38 @@ static void pwm_mediatek_clk_disable(struct pwm_chip *chip,
+@@ -107,14 +114,38 @@ static void pwm_mediatek_clk_disable(struct pwm_chip *chip,
  static inline u32 pwm_mediatek_readl(struct pwm_mediatek_chip *chip,
  				     unsigned int num, unsigned int offset)
  {
@@ -73,7 +82,7 @@
  }
  
  static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
-@@ -281,36 +311,49 @@ static int pwm_mediatek_remove(struct platform_device *pdev)
+@@ -280,36 +311,49 @@ static int pwm_mediatek_remove(struct platform_device *pdev)
  static const struct pwm_mediatek_of_data mt2712_pwm_data = {
  	.num_pwms = 8,
  	.pwm45_fixup = false,
@@ -123,7 +132,7 @@
  };
  
  static const struct of_device_id pwm_mediatek_of_match[] = {
-@@ -319,6 +362,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
+@@ -318,6 +362,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
  	{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
  	{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
  	{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
@@ -131,3 +140,6 @@
  	{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
  	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
  	{ },
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2132-add-pwm-feature-in-mt7988-project.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2132-add-pwm-feature-in-mt7988-project.patch
index 8268e7d..afa7720 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2132-add-pwm-feature-in-mt7988-project.patch
@@ -1,9 +1,19 @@
+From 1ad5b06d70ce07cd377d6a9580b922b1fa68e674 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:07 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2132-add-pwm-feature-in-mt7988-project.patch]
+
+---
+ drivers/pwm/pwm-mediatek.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
 diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
-index 3a5a456..6d6206e 100644
+index f4393bd46..9701092e7 100644
 --- a/drivers/pwm/pwm-mediatek.c
 +++ b/drivers/pwm/pwm-mediatek.c
 @@ -350,6 +350,12 @@ static const struct pwm_mediatek_of_data mt7986_pwm_data = {
- 	.reg_ver = REG_V2,
+ 	.reg_ver = REG_V1,
  };
  
 +static const struct pwm_mediatek_of_data mt7988_pwm_data = {
@@ -23,3 +33,6 @@
  	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
  	{ },
  };
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2133-pwm-mediatek-add-longer-period-support.patch
similarity index 85%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2133-pwm-mediatek-add-longer-period-support.patch
index 0934ae2..79afa46 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2133-pwm-mediatek-add-longer-period-support.patch
@@ -1,5 +1,15 @@
+From 58d5a373d2d42b5292c1c2242133bcf0b082c6e0 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:07 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2133-pwm-mediatek-add-longer-period-support.patch]
+
+---
+ drivers/pwm/pwm-mediatek.c | 34 ++++++++++++++++++++++++++++++----
+ 1 file changed, 30 insertions(+), 4 deletions(-)
+
 diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
-index 9701092..79d15a9 100644
+index 9701092e7..79d15a9c0 100644
 --- a/drivers/pwm/pwm-mediatek.c
 +++ b/drivers/pwm/pwm-mediatek.c
 @@ -152,8 +152,11 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -63,3 +73,6 @@
  	pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period);
  	pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty);
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2140-mtk-thermal-add-lvts-support.patch
similarity index 71%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2140-mtk-thermal-add-lvts-support.patch
index 1591144..a9ca6d7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2140-mtk-thermal-add-lvts-support.patch
@@ -1,5 +1,15 @@
+From 23c38736374866e0f1423dde94ac6e80eb644132 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:08 +0800
+Subject: [PATCH] [slow-speed-io][999-2140-mtk-thermal-add-lvts-support.patch]
+
+---
+ drivers/thermal/Kconfig  | 5 +++++
+ drivers/thermal/Makefile | 1 +
+ 2 files changed, 6 insertions(+)
+
 diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
-index 001a21ab..67d3da48 100644
+index 001a21abc..67d3da488 100644
 --- a/drivers/thermal/Kconfig
 +++ b/drivers/thermal/Kconfig
 @@ -348,6 +348,11 @@ config MTK_THERMAL
@@ -15,7 +25,7 @@
  depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
  source "drivers/thermal/intel/Kconfig"
 diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
-index 74a37c7f..6be9ff19 100644
+index 74a37c7f8..6be9ff194 100644
 --- a/drivers/thermal/Makefile
 +++ b/drivers/thermal/Makefile
 @@ -51,6 +51,7 @@ obj-$(CONFIG_QCOM_TSENS)	+= qcom/
@@ -26,3 +36,6 @@
  obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
  obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o
  obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0400-sound-add-some-helpers-to-control-mtk_memif.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2150-sound-add-some-helpers-to-control-mtk_memif.patch
similarity index 87%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0400-sound-add-some-helpers-to-control-mtk_memif.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2150-sound-add-some-helpers-to-control-mtk_memif.patch
index ddeb5a4..85c5ceb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0400-sound-add-some-helpers-to-control-mtk_memif.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2150-sound-add-some-helpers-to-control-mtk_memif.patch
@@ -1,6 +1,20 @@
+From 21c1013ecce400652b42489935190df542c9fa4b Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:08 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2150-sound-add-some-helpers-to-control-mtk_memif.patch]
+
+---
+ sound/soc/mediatek/common/mtk-afe-fe-dai.c | 216 +++++++++++++++++++++
+ sound/soc/mediatek/common/mtk-afe-fe-dai.h |  16 ++
+ sound/soc/mediatek/common/mtk-base-afe.h   |  28 ++-
+ 3 files changed, 259 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+index 10ea4fdbe..309dc1ef6 100644
 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
 +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
-@@ -361,6 +361,222 @@
+@@ -361,6 +361,222 @@ int mtk_afe_dai_resume(struct snd_soc_dai *dai)
  }
  EXPORT_SYMBOL_GPL(mtk_afe_dai_resume);
  
@@ -223,9 +237,11 @@
  MODULE_DESCRIPTION("Mediatek simple fe dai operator");
  MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
  MODULE_LICENSE("GPL v2");
+diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.h b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
+index 55074fb98..507e3e7c3 100644
 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h
 +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.h
-@@ -34,4 +34,20 @@
+@@ -34,4 +34,20 @@ int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id);
  int mtk_afe_dai_suspend(struct snd_soc_dai *dai);
  int mtk_afe_dai_resume(struct snd_soc_dai *dai);
  
@@ -246,9 +262,11 @@
 +int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe,
 +			    int id, int pbuf_size);
  #endif
+diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h
+index 60cb609a9..a8cf44d98 100644
 --- a/sound/soc/mediatek/common/mtk-base-afe.h
 +++ b/sound/soc/mediatek/common/mtk-base-afe.h
-@@ -16,21 +16,38 @@
+@@ -16,21 +16,38 @@ struct mtk_base_memif_data {
  	const char *name;
  	int reg_ofs_base;
  	int reg_ofs_cur;
@@ -288,7 +306,7 @@
  };
  
  struct mtk_base_irq_data {
-@@ -84,6 +101,12 @@
+@@ -84,6 +101,12 @@ struct mtk_base_afe {
  			unsigned int rate);
  	int (*irq_fs)(struct snd_pcm_substream *substream,
  		      unsigned int rate);
@@ -301,7 +319,7 @@
  
  	void *platform_priv;
  };
-@@ -95,6 +118,9 @@
+@@ -95,6 +118,9 @@ struct mtk_base_afe_memif {
  	const struct mtk_base_memif_data *data;
  	int irq_usage;
  	int const_irq;
@@ -311,3 +329,6 @@
  };
  
  struct mtk_base_afe_irq {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0401-sound-refine-hw-params-and-hw-prepare.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2151-sound-refine-hw-params-and-hw-prepare.patch
similarity index 87%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0401-sound-refine-hw-params-and-hw-prepare.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2151-sound-refine-hw-params-and-hw-prepare.patch
index 3e24d51..f097f4a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0401-sound-refine-hw-params-and-hw-prepare.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2151-sound-refine-hw-params-and-hw-prepare.patch
@@ -1,3 +1,15 @@
+From 35cc92b8996980021f881a202b8e1233ca41eb0d Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:08 +0800
+Subject: [PATCH] 
+ [slow-speed-io][999-2151-sound-refine-hw-params-and-hw-prepare.patch]
+
+---
+ sound/soc/mediatek/common/mtk-afe-fe-dai.c | 143 +++++++++++----------
+ 1 file changed, 77 insertions(+), 66 deletions(-)
+
+diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+index 309dc1ef6..e761cb66b 100644
 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
 +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
 @@ -6,11 +6,13 @@
@@ -14,7 +26,7 @@
  #include "mtk-afe-fe-dai.h"
  #include "mtk-base-afe.h"
  
-@@ -120,50 +122,64 @@
+@@ -120,50 +122,64 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
  {
  	struct snd_soc_pcm_runtime *rtd = substream->private_data;
  	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
@@ -49,10 +61,7 @@
 -			       1, msb_at_bit33, memif->data->msb_shift);
 +	if (afe->request_dram_resource)
 +		afe->request_dram_resource(afe->dev);
- 
--	/* set channel */
--	if (memif->data->mono_shift >= 0) {
--		unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
++
 +	dev_dbg(afe->dev, "%s(), %s, ch %d, rate %d, fmt %d, dma_addr %pad, dma_area %p, dma_bytes 0x%zx\n",
 +		__func__, memif->data->name,
 +		channels, rate, format,
@@ -74,9 +83,12 @@
 +		return ret;
 +	}
  
+ 	/* set channel */
+-	if (memif->data->mono_shift >= 0) {
+-		unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
+-
 -		mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
 -				       1, mono, memif->data->mono_shift);
-+	/* set channel */
 +	ret = mtk_memif_set_channel(afe, id, channels);
 +	if (ret) {
 +		dev_err(afe->dev, "%s(), error, id %d, set channel %d, ret %d\n",
@@ -112,7 +124,7 @@
  
  	return 0;
  }
-@@ -172,6 +188,11 @@
+@@ -172,6 +188,11 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_params);
  int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream,
  		       struct snd_soc_dai *dai)
  {
@@ -124,7 +136,7 @@
  	return snd_pcm_lib_free_pages(substream);
  }
  EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free);
-@@ -182,20 +203,25 @@
+@@ -182,20 +203,25 @@ int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
  	struct snd_soc_pcm_runtime *rtd = substream->private_data;
  	struct snd_pcm_runtime * const runtime = substream->runtime;
  	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
@@ -154,7 +166,7 @@
  
  		/* set irq counter */
  		mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
-@@ -219,15 +245,19 @@
+@@ -219,15 +245,19 @@ int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
  		return 0;
  	case SNDRV_PCM_TRIGGER_STOP:
  	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -177,7 +189,7 @@
  	default:
  		return -EINVAL;
  	}
-@@ -239,34 +269,15 @@
+@@ -239,34 +269,15 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
  {
  	struct snd_soc_pcm_runtime *rtd  = substream->private_data;
  	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
@@ -219,3 +231,6 @@
  	return 0;
  }
  EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0402-sound-add-mt7986-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0402-sound-add-mt7986-driver.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch
index 973f565..41eb05e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0402-sound-add-mt7986-driver.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch
@@ -1,6 +1,18 @@
+From 593cfdef7ef160c49db5c7ae315cb963f32a947a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:08 +0800
+Subject: [PATCH] [slow-speed-io][999-2152-sound-add-mt7986-driver.patch]
+
+---
+ sound/soc/mediatek/Kconfig  | 30 ++++++++++++++++++++++++++++++
+ sound/soc/mediatek/Makefile |  1 +
+ 2 files changed, 31 insertions(+)
+
+diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
+index 111e44b64..25e392428 100644
 --- a/sound/soc/mediatek/Kconfig
 +++ b/sound/soc/mediatek/Kconfig
-@@ -53,6 +53,36 @@
+@@ -53,6 +53,36 @@ config SND_SOC_MT6797_MT6351
  	  Select Y if you have such device.
  	  If unsure select "N".
  
@@ -37,6 +49,8 @@
  config SND_SOC_MT8173
  	tristate "ASoC support for Mediatek MT8173 chip"
  	depends on ARCH_MEDIATEK
+diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
+index 76032cae6..9690326b2 100644
 --- a/sound/soc/mediatek/Makefile
 +++ b/sound/soc/mediatek/Makefile
 @@ -2,5 +2,6 @@
@@ -46,3 +60,6 @@
 +obj-$(CONFIG_SND_SOC_MT79XX) += mt79xx/
  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0801-mtk-sd-add-mt7986-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2300-mtk-sd-add-mt7986-support.patch
similarity index 60%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0801-mtk-sd-add-mt7986-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2300-mtk-sd-add-mt7986-support.patch
index 6b76993..5a36ab0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0801-mtk-sd-add-mt7986-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2300-mtk-sd-add-mt7986-support.patch
@@ -1,6 +1,17 @@
+From b4ad228b3e415f980932a2200d93b56f135e6bc8 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:09 +0800
+Subject: [PATCH] [spi-and-storage][999-2300-mtk-sd-add-mt7986-support.patch]
+
+---
+ drivers/mmc/host/mtk-sd.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 1254a5650..b25e8567f 100644
 --- a/drivers/mmc/host/mtk-sd.c
 +++ b/drivers/mmc/host/mtk-sd.c
-@@ -508,6 +508,18 @@ static const struct mtk_mmc_compatible m
+@@ -508,6 +508,18 @@ static const struct mtk_mmc_compatible mt7622_compat = {
  	.support_64g = false,
  };
  
@@ -19,7 +30,7 @@
  static const struct mtk_mmc_compatible mt8516_compat = {
  	.clk_div_bits = 12,
  	.hs400_tune = false,
-@@ -537,6 +549,7 @@ static const struct of_device_id msdc_of
+@@ -537,6 +549,7 @@ static const struct of_device_id msdc_of_ids[] = {
  	{ .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat},
  	{ .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat},
  	{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat},
@@ -27,3 +38,6 @@
  	{ .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat},
  	{ .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat},
  	{}
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2301-mtk-sd-Add-subsys-clock-control.patch
similarity index 81%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2301-mtk-sd-Add-subsys-clock-control.patch
index 8732cef..9ac8a25 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2301-mtk-sd-Add-subsys-clock-control.patch
@@ -1,3 +1,15 @@
+From 80d83b8abe9bc8878ba7a40b4e399b8ea2ff8ad2 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:09 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2301-mtk-sd-Add-subsys-clock-control.patch]
+
+---
+ drivers/mmc/host/mtk-sd.c | 76 +++++++++++++++++++++++++++++----------
+ 1 file changed, 58 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index b25e8567f..ef344a4bd 100644
 --- a/drivers/mmc/host/mtk-sd.c
 +++ b/drivers/mmc/host/mtk-sd.c
 @@ -33,6 +33,7 @@
@@ -17,7 +29,7 @@
  	u32 mclk;		/* mmc subsystem clock frequency */
  	u32 src_clk_freq;	/* source clock frequency */
  	unsigned char timing;
-@@ -745,6 +748,7 @@ static void msdc_set_timeout(struct msdc
+@@ -745,6 +748,7 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
  
  static void msdc_gate_clock(struct msdc_host *host)
  {
@@ -25,7 +37,7 @@
  	clk_disable_unprepare(host->src_clk_cg);
  	clk_disable_unprepare(host->src_clk);
  	clk_disable_unprepare(host->bus_clk);
-@@ -753,10 +757,18 @@ static void msdc_gate_clock(struct msdc_
+@@ -753,10 +757,18 @@ static void msdc_gate_clock(struct msdc_host *host)
  
  static void msdc_ungate_clock(struct msdc_host *host)
  {
@@ -44,7 +56,7 @@
  	while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
  		cpu_relax();
  }
-@@ -2195,6 +2207,50 @@ static void msdc_of_property_parse(struc
+@@ -2195,6 +2207,50 @@ static void msdc_of_property_parse(struct platform_device *pdev,
  		host->hs400_cmd_resp_sel_rising = false;
  }
  
@@ -95,7 +107,7 @@
  static int msdc_drv_probe(struct platform_device *pdev)
  {
  	struct mmc_host *mmc;
-@@ -2235,25 +2291,9 @@ static int msdc_drv_probe(struct platfor
+@@ -2235,25 +2291,9 @@ static int msdc_drv_probe(struct platform_device *pdev)
  	if (ret)
  		goto host_free;
  
@@ -123,3 +135,6 @@
  
  	host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
  								"hrst");
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0490-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
similarity index 86%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0490-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
index 6d2a4b8..42467b6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0490-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
@@ -1,3 +1,15 @@
+From 2c71a01b9363f44ca077ec0e27b6a06a15617497 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:14 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch]
+
+---
+ drivers/mtd/nand/spi/winbond.c | 129 ++++++++++++++++++++++++++++++++-
+ 1 file changed, 127 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
+index 766844283..6473b0367 100644
 --- a/drivers/mtd/nand/spi/winbond.c
 +++ b/drivers/mtd/nand/spi/winbond.c
 @@ -15,6 +15,23 @@
@@ -24,7 +36,7 @@
  static SPINAND_OP_VARIANTS(read_cache_variants,
  		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-@@ -31,6 +48,29 @@ static SPINAND_OP_VARIANTS(update_cache_
+@@ -31,6 +48,29 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
  		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
  		SPINAND_PROG_LOAD(false, 0, NULL, 0));
  
@@ -54,7 +66,7 @@
  static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
  				  struct mtd_oob_region *region)
  {
-@@ -74,9 +114,61 @@ static int w25m02gv_select_target(struct
+@@ -74,9 +114,61 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
  	return spi_mem_exec_op(spinand->spimem, &op);
  }
  
@@ -117,7 +129,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -85,8 +177,18 @@ static const struct spinand_info winbond
+@@ -85,8 +177,18 @@ static const struct spinand_info winbond_spinand_table[] = {
  		     0,
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
  		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
@@ -137,7 +149,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -94,6 +196,29 @@ static const struct spinand_info winbond
+@@ -94,6 +196,29 @@ static const struct spinand_info winbond_spinand_table[] = {
  					      &update_cache_variants),
  		     0,
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
@@ -167,3 +179,6 @@
  };
  
  static int winbond_spinand_init(struct spinand_device *spinand)
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
new file mode 100644
index 0000000..b19492b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
@@ -0,0 +1,26 @@
+From 6d8d4dc76ac31cfdecef99c72aad6a65f963d4a0 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:14 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch]
+
+---
+ drivers/mtd/nand/spi/macronix.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index 25319b4f8..d3ae24ecc 100644
+--- a/drivers/mtd/nand/spi/macronix.c
++++ b/drivers/mtd/nand/spi/macronix.c
+@@ -86,7 +86,7 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
+ 		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
+ 			return nand->eccreq.strength;
+ 
+-		if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr))
++		if (eccsr > nand->eccreq.strength || !eccsr)
+ 			return nand->eccreq.strength;
+ 
+ 		return eccsr;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2332-mtd-add-mtk-snand-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2332-mtd-add-mtk-snand-driver.patch
new file mode 100644
index 0000000..a020a2f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2332-mtd-add-mtk-snand-driver.patch
@@ -0,0 +1,38 @@
+From 6fa8802185f08391dd3eb6e0609268e1108a7f57 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:15 +0800
+Subject: [PATCH] [spi-and-storage][999-2332-mtd-add-mtk-snand-driver.patch]
+
+---
+ drivers/mtd/Kconfig  | 2 ++
+ drivers/mtd/Makefile | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
+index 3ed42b402..4b6f9d851 100644
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -230,6 +230,8 @@ source "drivers/mtd/hyperbus/Kconfig"
+ 
+ source "drivers/mtd/nmbm/Kconfig"
+ 
++source "drivers/mtd/mtk-snand/Kconfig"
++
+ source "drivers/mtd/composite/Kconfig"
+ 
+ endif # MTD
+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
+index f27f66784..df786f994 100644
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -35,5 +35,7 @@ obj-$(CONFIG_MTD_HYPERBUS)	+= hyperbus/
+ 
+ obj-y				+= nmbm/
+ 
++obj-$(CONFIG_MTK_SPI_NAND)	+= mtk-snand/
++
+ # Composite drivers must be loaded last
+ obj-y				+= composite/
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/412-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2333-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/412-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2333-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch
index 32bce58..d37dd56 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/412-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2333-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch
@@ -1,6 +1,18 @@
+From 39ee4e9fb5fd3ce678223147df9d9bef0ce822cd Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:15 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2333-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch]
+
+---
+ drivers/mtd/nand/spi/gigadevice.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index 937a04ce6..ce88f0c91 100644
 --- a/drivers/mtd/nand/spi/gigadevice.c
 +++ b/drivers/mtd/nand/spi/gigadevice.c
-@@ -39,6 +39,15 @@ static SPINAND_OP_VARIANTS(read_cache_va
+@@ -39,6 +39,15 @@ static SPINAND_OP_VARIANTS(read_cache_variants_f,
  		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
  
@@ -16,7 +28,7 @@
  static SPINAND_OP_VARIANTS(write_cache_variants,
  		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
  		SPINAND_PROG_LOAD(true, 0, NULL, 0));
-@@ -265,6 +274,16 @@ static int gd5fxgq4ufxxg_ecc_get_status(
+@@ -236,6 +245,16 @@ static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
  }
  
  static const struct spinand_info gigadevice_spinand_table[] = {
@@ -33,7 +45,7 @@
  	SPINAND_INFO("GD5F1GQ4xA",
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-@@ -337,7 +356,7 @@ static const struct spinand_info gigadev
+@@ -290,7 +309,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(4, 512),
@@ -42,3 +54,6 @@
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/413-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2334-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch
similarity index 86%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/413-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2334-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch
index 83e4c71..c609bd7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/413-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2334-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch
@@ -1,6 +1,18 @@
+From b8ffe42101eb8abfb6530396e0c74a85b43eed44 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:15 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2334-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch]
+
+---
+ drivers/mtd/nand/spi/gigadevice.c | 98 +++++++++++++++++++++++++++++--
+ 1 file changed, 94 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index ce88f0c91..a4e89529d 100644
 --- a/drivers/mtd/nand/spi/gigadevice.c
 +++ b/drivers/mtd/nand/spi/gigadevice.c
-@@ -39,8 +39,9 @@ static SPINAND_OP_VARIANTS(read_cache_va
+@@ -39,8 +39,9 @@ static SPINAND_OP_VARIANTS(read_cache_variants_f,
  		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
  
@@ -12,7 +24,7 @@
  		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
-@@ -48,6 +49,15 @@ static SPINAND_OP_VARIANTS(gd5f1gq5_read
+@@ -48,6 +49,15 @@ static SPINAND_OP_VARIANTS(gd5f1gq5_read_cache_variants,
  		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
  
@@ -28,7 +40,7 @@
  static SPINAND_OP_VARIANTS(write_cache_variants,
  		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
  		SPINAND_PROG_LOAD(true, 0, NULL, 0));
-@@ -249,7 +259,7 @@ static const struct spinand_info gigadev
+@@ -249,7 +259,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  	             SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01),
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(8, 512),
@@ -37,7 +49,7 @@
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     0,
-@@ -309,7 +319,87 @@ static const struct spinand_info gigadev
+@@ -309,7 +319,87 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
  		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(4, 512),
@@ -126,3 +138,6 @@
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/414-mtd-spinand-fix-gigadevice-read-dummy.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2335-mtd-spinand-fix-gigadevice-read-dummy.patch
similarity index 68%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/414-mtd-spinand-fix-gigadevice-read-dummy.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2335-mtd-spinand-fix-gigadevice-read-dummy.patch
index 5c5af56..977c65c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/414-mtd-spinand-fix-gigadevice-read-dummy.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2335-mtd-spinand-fix-gigadevice-read-dummy.patch
@@ -1,6 +1,18 @@
+From be41be0e740933fa976ad2990b94ef1e62542a8e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:15 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2335-mtd-spinand-fix-gigadevice-read-dummy.patch]
+
+---
+ drivers/mtd/nand/spi/gigadevice.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index a4e89529d..b163ea5dc 100644
 --- a/drivers/mtd/nand/spi/gigadevice.c
 +++ b/drivers/mtd/nand/spi/gigadevice.c
-@@ -379,7 +379,7 @@ static const struct spinand_info gigadev
+@@ -379,7 +379,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x31),
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(4, 512),
@@ -9,7 +21,7 @@
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
-@@ -389,17 +389,17 @@ static const struct spinand_info gigadev
+@@ -389,17 +389,17 @@ static const struct spinand_info gigadevice_spinand_table[] = {
  		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x32),
  		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
  		     NAND_ECCREQ(4, 512),
@@ -30,3 +42,6 @@
  					      &write_cache_variants,
  					      &update_cache_variants),
  		     SPINAND_HAS_QE_BIT,
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2336-mtd-spinand-fix-F50L1G41LB-ecc-check.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2336-mtd-spinand-fix-F50L1G41LB-ecc-check.patch
new file mode 100644
index 0000000..644c6b3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2336-mtd-spinand-fix-F50L1G41LB-ecc-check.patch
@@ -0,0 +1,27 @@
+From c93adec4ad0e8ca47f1a622fb3a5ae445251af36 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:16 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2336-mtd-spinand-fix-F50L1G41LB-ecc-check.patch]
+
+---
+ drivers/mtd/nand/spi/gigadevice.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
+index b163ea5dc..6ee569de2 100644
+--- a/drivers/mtd/nand/spi/gigadevice.c
++++ b/drivers/mtd/nand/spi/gigadevice.c
+@@ -263,8 +263,7 @@ static const struct spinand_info gigadevice_spinand_table[] = {
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
+-				     gd5fxgq4xa_ecc_get_status)),
++		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, NULL)),
+ 	SPINAND_INFO("GD5F1GQ4xA",
+ 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2337-mtd-spinor-support-EN25QX128A.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2337-mtd-spinor-support-EN25QX128A.patch
new file mode 100644
index 0000000..239d246
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2337-mtd-spinor-support-EN25QX128A.patch
@@ -0,0 +1,27 @@
+From 6e915b8dd6ddb6f56ebf23123c26fb90fd5f5198 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:16 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2337-mtd-spinor-support-EN25QX128A.patch]
+
+---
+ drivers/mtd/spi-nor/spi-nor.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index 2599bbea8..8d2bc03cd 100644
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -2249,6 +2249,9 @@ static const struct flash_info spi_nor_ids[] = {
+ 	{ "en25qh64",   INFO(0x1c7017, 0, 64 * 1024,  128,
+ 			SECT_4K | SPI_NOR_DUAL_READ) },
+ 	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
++	{ "en25qx128",	INFO(0x1c7118, 0, 64 * 1024,  256,
++			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
++			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ 	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
+ 	{ "en25s64",	INFO(0x1c3817, 0, 64 * 1024,  128, SECT_4K) },
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2338-mtd-tests-fix-pagetest-load.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2338-mtd-tests-fix-pagetest-load.patch
new file mode 100644
index 0000000..776d990
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2338-mtd-tests-fix-pagetest-load.patch
@@ -0,0 +1,56 @@
+From eaa6d1a21a8ea3c68498ef4ff0cf91d109e4d821 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:16 +0800
+Subject: [PATCH] [spi-and-storage][999-2338-mtd-tests-fix-pagetest-load.patch]
+
+---
+ drivers/mtd/tests/pagetest.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c
+index 8eb40b6e6..d1c8a932e 100644
+--- a/drivers/mtd/tests/pagetest.c
++++ b/drivers/mtd/tests/pagetest.c
+@@ -25,6 +25,10 @@ static int dev = -EINVAL;
+ module_param(dev, int, S_IRUGO);
+ MODULE_PARM_DESC(dev, "MTD device number to use");
+ 
++static int count = 10000;
++module_param(count, int, 0444);
++MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
++
+ static struct mtd_info *mtd;
+ static unsigned char *twopages;
+ static unsigned char *writebuf;
+@@ -331,7 +335,7 @@ static int __init mtd_pagetest_init(void)
+ 		return -EINVAL;
+ 	}
+ 
+-	pr_info("MTD device: %d\n", dev);
++	pr_info("MTD device: %d count:%d\n", dev, count);
+ 
+ 	mtd = get_mtd_device(NULL, dev);
+ 	if (IS_ERR(mtd)) {
+@@ -376,6 +380,7 @@ static int __init mtd_pagetest_init(void)
+ 	if (err)
+ 		goto out;
+ 
++LOOP:
+ 	/* Erase all eraseblocks */
+ 	pr_info("erasing whole device\n");
+ 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
+@@ -435,7 +440,10 @@ static int __init mtd_pagetest_init(void)
+ 	if (err)
+ 		goto out;
+ 
+-	pr_info("finished with %d errors\n", errcnt);
++	pr_info("finished with %d errors count:%d\n", errcnt, count);
++	
++	if (count-- > 0)
++		goto LOOP;
+ out:
+ 
+ 	kfree(bbt);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
similarity index 87%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
index 374531b..cf785fe 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
@@ -1,9 +1,9 @@
-From 6bd88d34cb5a5cb1d7c544c9f5b430105b000308 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:39:56 +0800
-Subject: [PATCH] drivers: mtd: spinand: Add calibration support for spinand
+From ddd2951e2f35477a81fb882a976a5a1fe981883d Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:17 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
  drivers/mtd/nand/spi/core.c | 58 +++++++++++++++++++++++++++++++++++++
  1 file changed, 58 insertions(+)
@@ -85,5 +85,5 @@
  	if (ret)
  		goto err_free_bufs;
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
similarity index 68%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
index fd1bd1a..b6a4255 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
@@ -1,16 +1,18 @@
-From b242e30661dac5c1c127999600029cd5b3f6b458 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:40:59 +0800
-Subject: [PATCH] drivers: mtd: spi-nor: Add calibration support for spi-nor
+From f392188951839efae7807b6287a62c78d1ed0088 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:17 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
- drivers/mtd/spi-nor/spi-nor.c | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
+ drivers/mtd/spi-nor/spi-nor.c | 40 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
 
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index 8d2bc03cd..198b57a92 100644
 --- a/drivers/mtd/spi-nor/spi-nor.c
 +++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -4897,6 +4897,35 @@ static void spi_nor_debugfs_init(struct
+@@ -4899,6 +4899,35 @@ static void spi_nor_debugfs_init(struct spi_nor *nor,
  					 info->id_len, info->id);
  }
  
@@ -46,7 +48,7 @@
  static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
  						       const char *name)
  {
-@@ -4971,6 +5000,17 @@ int spi_nor_scan(struct spi_nor *nor, co
+@@ -4973,6 +5002,17 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
  	if (!nor->bouncebuf)
  		return -ENOMEM;
  
@@ -64,3 +66,6 @@
  	info = spi_nor_get_flash_info(nor, name);
  	if (IS_ERR(info))
  		return PTR_ERR(info);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8004-nvmem-core-Add-functions-to-make-number-reading-easy.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch
similarity index 69%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8004-nvmem-core-Add-functions-to-make-number-reading-easy.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch
index 969ec3f..a4147dd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8004-nvmem-core-Add-functions-to-make-number-reading-easy.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch
@@ -1,65 +1,16 @@
-From 8dc0b1158dcffd78ea2b3a5604b82ee826de687b Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Mon, 8 Nov 2021 13:58:51 +0800
-Subject: [PATCH 1/5] nvmem: core: Add functions to make number reading easy
+From 21a99150a566b69edc7f3b9bc369bb4525e04acd Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:17 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch]
 
-Sometimes the clients of nvmem just want to get a number out of
-nvmem. They don't want to think about exactly how many bytes the nvmem
-cell took up. They just want the number. Let's make it easy.
-
-In general this concept is useful because nvmem space is precious and
-usually the fewest bits are allocated that will hold a given value on
-a given system. However, even though small numbers might be fine on
-one system that doesn't mean that logically the number couldn't be
-bigger. Imagine nvmem containing a max frequency for a component. On
-one system perhaps that fits in 16 bits. On another system it might
-fit in 32 bits. The code reading this number doesn't care--it just
-wants the number.
-
-We'll provide two functions: nvmem_cell_read_variable_le_u32() and
-nvmem_cell_read_variable_le_u64().
-
-Comparing these to the existing functions like nvmem_cell_read_u32():
-* These new functions have no problems if the value was stored in
-  nvmem in fewer bytes. It's OK to use these function as long as the
-  value stored will fit in 32-bits (or 64-bits).
-* These functions avoid problems that the earlier APIs had with bit
-  offsets. For instance, you can't use nvmem_cell_read_u32() to read a
-  value has nbits=32 and bit_offset=4 because the nvmem cell must be
-  at least 5 bytes big to hold this value. The new API accounts for
-  this and works fine.
-* These functions make it very explicit that they assume that the
-  number was stored in little endian format. The old functions made
-  this assumption whenever bit_offset was non-zero (see
-  nvmem_shift_read_buffer_in_place()) but didn't whenever the
-  bit_offset was zero.
-
-NOTE: it's assumed that we don't need an 8-bit or 16-bit version of
-this function. The 32-bit version of the function can be used to read
-8-bit or 16-bit data.
-
-At the moment, I'm only adding the "unsigned" versions of these
-functions, but if it ends up being useful someone could add a "signed"
-version that did 2's complement sign extension.
-
-At the moment, I'm only adding the "little endian" versions of these
-functions. Adding the "big endian" version would require adding "big
-endian" support to nvmem_shift_read_buffer_in_place().
-
-Signed-off-by: Douglas Anderson <dianders@chromium.org>
-Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-Link: https://lore.kernel.org/r/20210330111241.19401-7-srinivas.kandagatla@linaro.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Change-Id: I3e1d96ec1680812d5e24681c79852c9b36899559
 ---
  drivers/nvmem/core.c           | 161 +++++++++++++++++++++++++++------
  include/linux/nvmem-consumer.h |  15 +++
  2 files changed, 150 insertions(+), 26 deletions(-)
 
 diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
-index c0f4324d8f7c..e26b25b5c288 100644
+index 19ac0d055..f65305b6d 100644
 --- a/drivers/nvmem/core.c
 +++ b/drivers/nvmem/core.c
 @@ -1102,16 +1102,8 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
@@ -270,10 +221,10 @@
  /**
   * nvmem_device_cell_read() - Read a given nvmem device and cell
 diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
-index 5c17cb733224..e328c0f7eef3 100644
+index 0f490b288..227b93158 100644
 --- a/include/linux/nvmem-consumer.h
 +++ b/include/linux/nvmem-consumer.h
-@@ -63,6 +63,10 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
+@@ -64,6 +64,10 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
  int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
  int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val);
  int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val);
@@ -284,7 +235,7 @@
  
  /* direct nvmem device read/write interface */
  struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
-@@ -134,6 +138,17 @@ static inline int nvmem_cell_read_u32(struct device *dev,
+@@ -135,6 +139,17 @@ static inline int nvmem_cell_read_u32(struct device *dev,
  {
  	return -EOPNOTSUPP;
  }
@@ -303,5 +254,5 @@
  static inline struct nvmem_device *nvmem_device_get(struct device *dev,
  						    const char *name)
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8005-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch
similarity index 62%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8005-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch
index 8de4c2a..c042918 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8005-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch
@@ -1,21 +1,15 @@
-From 44ae4ed142265a6d50a9d3e6f4c395f97b6849ab Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Sat, 6 Nov 2021 20:06:30 +0800
-Subject: [PATCH 2/5] nvmem: mtk-efuse: support minimum one byte access stride
- and granularity
+From 6b7498e172d4458499a3ba406bf7975478f46d21 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:17 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch]
 
-In order to support nvmem bits property, should support minimum 1 byte
-read stride and minimum 1 byte read granularity at the same time.
-
-Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Change-Id: Iafe1ebf195d58a3e9e3518913f795d14a01dfd3b
 ---
  drivers/nvmem/mtk-efuse.c | 13 +++++++------
  1 file changed, 7 insertions(+), 6 deletions(-)
 
 diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
-index 856d9c3fc38e..2e728fed0b49 100644
+index 856d9c3fc..2e728fed0 100644
 --- a/drivers/nvmem/mtk-efuse.c
 +++ b/drivers/nvmem/mtk-efuse.c
 @@ -19,11 +19,12 @@ static int mtk_reg_read(void *context,
@@ -47,5 +41,5 @@
  	econfig.reg_write = mtk_reg_write;
  	econfig.size = resource_size(res);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-add-spimem-support-to-mtk-spi.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2361-add-spimem-support-to-mtk-spi.patch
similarity index 94%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-add-spimem-support-to-mtk-spi.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2361-add-spimem-support-to-mtk-spi.patch
index d50aa25..2d2aeaa 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0666-add-spimem-support-to-mtk-spi.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2361-add-spimem-support-to-mtk-spi.patch
@@ -1,21 +1,16 @@
-From 675b477b2a50b2fb97f35944756f89644bf70092 Mon Sep 17 00:00:00 2001
-From: Qii Wang <qii.wang@mediatek.com>
-Date: Tue, 5 Jan 2021 16:48:39 +0800
-Subject: [PATCH] spi: mediatek: support IPM Design
+From 85e3059aee9943eddfd2b7c9fc83481751005c09 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:18 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2361-add-spimem-support-to-mtk-spi.patch]
 
-[Description]
-1. support sigle mode;
-2. support dual/quad mode with spi-mem framework.
-
-Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
-Reviewed-by: Qii Wang <qii.wang@mediatek.com>
 ---
  drivers/spi/spi-mt65xx.c                 | 395 +++++++++++++++++++++--
  include/linux/platform_data/spi-mt65xx.h |   2 +-
  2 files changed, 370 insertions(+), 27 deletions(-)
 
 diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index 8acf24f7c..9183c64e4 100644
+index 29d44f5d5..dbb471769 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -17,6 +17,7 @@
@@ -282,8 +277,8 @@
 +	mtk_spi_prepare_transfer(master, xfer->speed_hz);
  	mtk_spi_setup_packet(master);
  
- 	cnt = xfer->len / 4;
-@@ -455,7 +553,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
+ 	if (xfer->tx_buf) {
+@@ -456,7 +554,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
  	mdata->cur_transfer = xfer;
  	mdata->num_xfered = 0;
  
@@ -292,7 +287,7 @@
  
  	cmd = readl(mdata->base + SPI_CMD_REG);
  	if (xfer->tx_buf)
-@@ -532,6 +630,13 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+@@ -533,6 +631,13 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
  	else
  		mdata->state = MTK_SPI_IDLE;
  
@@ -306,7 +301,7 @@
  	if (!master->can_dma(master, NULL, trans)) {
  		if (trans->rx_buf) {
  			cnt = mdata->xfer_len / 4;
-@@ -615,12 +720,241 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+@@ -616,12 +721,241 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
  	return IRQ_HANDLED;
  }
  
@@ -549,7 +544,7 @@
  	int i, irq, ret, addr_bits;
  
  	master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
-@@ -629,7 +963,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -630,7 +964,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		return -ENOMEM;
  	}
  
@@ -558,7 +553,7 @@
  	master->dev.of_node = pdev->dev.of_node;
  	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
  
-@@ -648,9 +982,25 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -649,9 +983,25 @@ static int mtk_spi_probe(struct platform_device *pdev)
  
  	mdata = spi_master_get_devdata(master);
  	mdata->dev_comp = of_id->data;
@@ -584,7 +579,7 @@
  	if (mdata->dev_comp->need_pad_sel) {
  		mdata->pad_num = of_property_count_u32_elems(
  			pdev->dev.of_node,
-@@ -683,15 +1033,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -684,15 +1034,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
  	}
  
  	platform_set_drvdata(pdev, master);
@@ -601,7 +596,7 @@
  	if (IS_ERR(mdata->base)) {
  		ret = PTR_ERR(mdata->base);
  		goto err_put_master;
-@@ -713,6 +1055,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -714,6 +1056,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		goto err_put_master;
  	}
  
@@ -609,7 +604,7 @@
  	mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk");
  	if (IS_ERR(mdata->parent_clk)) {
  		ret = PTR_ERR(mdata->parent_clk);
-@@ -750,7 +1093,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -751,7 +1094,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
  	clk_disable_unprepare(mdata->spi_clk);
  
  	pm_runtime_enable(&pdev->dev);
@@ -632,5 +627,5 @@
  };
  #endif
 -- 
-2.17.1
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2362-spi-mtk-nor-fix-timeout-calculation-overflow.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2362-spi-mtk-nor-fix-timeout-calculation-overflow.patch
new file mode 100644
index 0000000..d7f7d9b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2362-spi-mtk-nor-fix-timeout-calculation-overflow.patch
@@ -0,0 +1,37 @@
+From 2231dfcbcffef50846a9c240651c62771d7e33b0 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:18 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2362-spi-mtk-nor-fix-timeout-calculation-overflow.patch]
+
+---
+ drivers/spi/spi-mtk-nor.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
+index c15a99105..4f72f08c0 100644
+--- a/drivers/spi/spi-mtk-nor.c
++++ b/drivers/spi/spi-mtk-nor.c
+@@ -89,7 +89,7 @@
+ // Buffered page program can do one 128-byte transfer
+ #define MTK_NOR_PP_SIZE			128
+ 
+-#define CLK_TO_US(sp, clkcnt)		((clkcnt) * 1000000 / sp->spi_freq)
++#define CLK_TO_US(sp, clkcnt)		DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)
+ 
+ struct mtk_nor {
+ 	struct spi_controller *ctlr;
+@@ -177,6 +177,10 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+ 	if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
+ 		if ((op->data.dir == SPI_MEM_DATA_IN) &&
+ 		    mtk_nor_match_read(op)) {
++			// limit size to prevent timeout calculation overflow
++			if (op->data.nbytes > 0x400000)
++				op->data.nbytes = 0x400000;
++
+ 			if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) ||
+ 			    (op->data.nbytes < MTK_NOR_DMA_ALIGN))
+ 				op->data.nbytes = 1;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2363-spi-mediatek-fix-timeout-for-large-data.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2363-spi-mediatek-fix-timeout-for-large-data.patch
new file mode 100644
index 0000000..2a05ef3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2363-spi-mediatek-fix-timeout-for-large-data.patch
@@ -0,0 +1,49 @@
+From 8efe8045522d7bd790b9ae7408c64f497a54e643 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:18 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2363-spi-mediatek-fix-timeout-for-large-data.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index dbb471769..871eff03f 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -721,6 +721,23 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
++static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
++                                      struct spi_mem_op *op)
++{
++	int opcode_len;
++
++	if(!op->data.nbytes)
++		return 0;
++
++	if (op->data.dir != SPI_MEM_NO_DATA) {
++		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
++		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE)
++			op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE -opcode_len;
++	}
++
++	return 0;
++}
++
+ static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
+ 				     const struct spi_mem_op *op)
+ {
+@@ -947,6 +964,7 @@ err_exit:
+ }
+ 
+ static const struct spi_controller_mem_ops mtk_spi_mem_ops = {
++	.adjust_op_size = mtk_spi_mem_adjust_op_size,
+ 	.supports_op = mtk_spi_mem_supports_op,
+ 	.exec_op = mtk_spi_mem_exec_op,
+ };
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2364-spi-mediatek-fix-dma-unmap-twice.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2364-spi-mediatek-fix-dma-unmap-twice.patch
new file mode 100644
index 0000000..997e16f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2364-spi-mediatek-fix-dma-unmap-twice.patch
@@ -0,0 +1,31 @@
+From 548735b3ae97333e3630febcf15298304aa42dcf Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:19 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2364-spi-mediatek-fix-dma-unmap-twice.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 871eff03f..3a8f67f1e 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -947,12 +947,10 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
+ 		reg_val &= ~SPI_CMD_RX_DMA;
+ 	writel(reg_val, mdata->base + SPI_CMD_REG);
+ 
++unmap_rx_dma:
+ 	if (op->data.dir == SPI_MEM_DATA_IN)
+ 		dma_unmap_single(mdata->dev, mdata->rx_dma,
+ 				 op->data.nbytes, DMA_FROM_DEVICE);
+-unmap_rx_dma:
+-	dma_unmap_single(mdata->dev, mdata->rx_dma,
+-			 op->data.nbytes, DMA_FROM_DEVICE);
+ unmap_tx_dma:
+ 	dma_unmap_single(mdata->dev, mdata->tx_dma,
+ 			 tx_size, DMA_TO_DEVICE);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2365-fix-SPIM-NAND-and-NOR-probing.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2365-fix-SPIM-NAND-and-NOR-probing.patch
new file mode 100644
index 0000000..02e460a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2365-fix-SPIM-NAND-and-NOR-probing.patch
@@ -0,0 +1,48 @@
+From 1a41f923f66c03c40e6703dd69f8bfbe2791ce70 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:19 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2365-fix-SPIM-NAND-and-NOR-probing.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 3a8f67f1e..05697e1d1 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -1072,7 +1072,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+ 		goto err_put_master;
+ 	}
+ 
+-/*
++
+ 	mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk");
+ 	if (IS_ERR(mdata->parent_clk)) {
+ 		ret = PTR_ERR(mdata->parent_clk);
+@@ -1100,17 +1100,17 @@ static int mtk_spi_probe(struct platform_device *pdev)
+ 		goto err_put_master;
+ 	}
+ 
+-	ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk);
++	/*ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret);
+ 		clk_disable_unprepare(mdata->spi_clk);
+ 		goto err_put_master;
+ 	}
+ 
+-	clk_disable_unprepare(mdata->spi_clk);
++	clk_disable_unprepare(mdata->sel_clk);*/
++
++	//pm_runtime_enable(&pdev->dev);
+ 
+-	pm_runtime_enable(&pdev->dev);
+-*/
+ 	ret = devm_spi_register_master(&pdev->dev, master);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "failed to register master (%d)\n", ret);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0670-fix-SPIM-dma-buffer-not-aligned.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2366-fix-SPIM-dma-buffer-not-aligned.patch
similarity index 68%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0670-fix-SPIM-dma-buffer-not-aligned.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2366-fix-SPIM-dma-buffer-not-aligned.patch
index d4534e7..fed7675 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0670-fix-SPIM-dma-buffer-not-aligned.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2366-fix-SPIM-dma-buffer-not-aligned.patch
@@ -1,6 +1,18 @@
+From 475f064022a716bda4574406d8365627c3bcf131 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:19 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2366-fix-SPIM-dma-buffer-not-aligned.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 33 +++++++++++++++++++++++----------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 05697e1d1..2883dc908 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
-@@ -184,7 +184,7 @@ static const struct mtk_spi_compatible m
+@@ -184,7 +184,7 @@ static const struct mtk_spi_compatible mt8183_compat = {
   */
  static const struct mtk_chip_config mtk_default_chip_info = {
  	.sample_sel = 0,
@@ -9,7 +21,7 @@
  };
  
  static const struct of_device_id mtk_spi_of_match[] = {
-@@ -730,8 +730,11 @@ static int mtk_spi_mem_adjust_op_size(st
+@@ -731,8 +731,11 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
  
  	if (op->data.dir != SPI_MEM_NO_DATA) {
  		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
@@ -22,7 +34,7 @@
  	}
  
  	return 0;
-@@ -758,10 +761,6 @@ static bool mtk_spi_mem_supports_op(stru
+@@ -759,10 +762,6 @@ static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
  			return false;
  	}
  
@@ -33,7 +45,7 @@
  	return true;
  }
  
-@@ -820,6 +819,7 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -821,6 +820,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  	struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master);
  	u32 reg_val, nio = 1, tx_size;
  	char *tx_tmp_buf;
@@ -41,7 +53,7 @@
  	int ret = 0;
  
  	mdata->use_spimem = true;
-@@ -914,10 +914,18 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -915,10 +915,18 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  	}
  
  	if (op->data.dir == SPI_MEM_DATA_IN) {
@@ -63,7 +75,7 @@
  		if (dma_mapping_error(mdata->dev, mdata->rx_dma)) {
  			ret = -ENOMEM;
  			goto unmap_tx_dma;
-@@ -947,9 +955,14 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -948,9 +956,14 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  	writel(reg_val, mdata->base + SPI_CMD_REG);
  
  unmap_rx_dma:
@@ -79,3 +91,6 @@
  unmap_tx_dma:
  	dma_unmap_single(mdata->dev, mdata->tx_dma,
  			 tx_size, DMA_TO_DEVICE);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2367-fix-mtk-nfi-driver-dependency.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2367-fix-mtk-nfi-driver-dependency.patch
new file mode 100644
index 0000000..9ef3678
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2367-fix-mtk-nfi-driver-dependency.patch
@@ -0,0 +1,25 @@
+From 8a165fdcdddc69e2bc048636695521d5b6966ff7 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:19 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2367-fix-mtk-nfi-driver-dependency.patch]
+
+---
+ drivers/spi/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index b26bf6b46..4b97ca45c 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -429,6 +429,7 @@ config SPI_MT65XX
+ 
+ config SPI_MTK_SNFI
+ 	tristate "MediaTek SPI NAND interface"
++	depends on MTD
+ 	select MTD_SPI_NAND
+ 	help
+ 	  This selects the SPI NAND FLASH interface(SNFI),
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2368-kernel-MT7988-fix-spi-dma-unmap.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2368-kernel-MT7988-fix-spi-dma-unmap.patch
new file mode 100644
index 0000000..4774cb3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2368-kernel-MT7988-fix-spi-dma-unmap.patch
@@ -0,0 +1,32 @@
+From f715b301cff26297a1f4af71e6982de3d56673dd Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:20 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2368-kernel-MT7988-fix-spi-dma-unmap.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 2883dc908..b03257132 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -957,12 +957,12 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
+ 
+ unmap_rx_dma:
+ 	if (op->data.dir == SPI_MEM_DATA_IN) {
++		dma_unmap_single(mdata->dev, mdata->rx_dma,
++				 op->data.nbytes, DMA_FROM_DEVICE);
+ 		if(!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
+ 			memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes);
+ 			kfree(rx_tmp_buf);
+ 		}
+-		dma_unmap_single(mdata->dev, mdata->rx_dma,
+-				 op->data.nbytes, DMA_FROM_DEVICE);
+ 	}
+ unmap_tx_dma:
+ 	dma_unmap_single(mdata->dev, mdata->tx_dma,
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9009-Add-spi-runtime-PM-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2369-Add-spi-runtime-PM-support.patch
similarity index 84%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9009-Add-spi-runtime-PM-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2369-Add-spi-runtime-PM-support.patch
index 8371b57..92dbb42 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9009-Add-spi-runtime-PM-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2369-Add-spi-runtime-PM-support.patch
@@ -1,22 +1,14 @@
-From 0c1e4af01506c913cc54e63f66bb5470f50790c7 Mon Sep 17 00:00:00 2001
-From: Leilk Liu <leilk.liu@mediatek.com>
-Date: Tue, 13 Jul 2021 21:45:59 +0800
-Subject: [PATCH] [Add spi runtime PM support]
+From c8ea5f2bbc2ece3efcb7b8c704a7bee4c5f7adef Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:20 +0800
+Subject: [PATCH] [spi-and-storage][999-2369-Add-spi-runtime-PM-support.patch]
 
-[Description]
-Add ahb clk and enable runtime pm
-
-[Release-log]
-N/A
-
-Change-Id: I0529f6e829f5fc4c5880508971c97b9434820340
-Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
 ---
  drivers/spi/spi-mt65xx.c | 77 ++++++++++++++++++++++++++++++++++------
  1 file changed, 67 insertions(+), 10 deletions(-)
 
 diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index 7e54984..ff2d825 100644
+index b03257132..7c3ee3381 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -119,6 +119,8 @@ struct mtk_spi_compatible {
@@ -74,7 +66,7 @@
  	},
  	{ .compatible = "mediatek,mt2701-spi",
  		.data = (void *)&mtk_common_compat,
-@@ -992,7 +1006,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -993,7 +1007,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		return -ENOMEM;
  	}
  
@@ -83,7 +75,7 @@
  	master->dev.of_node = pdev->dev.of_node;
  	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
  
-@@ -1106,22 +1120,40 @@ static int mtk_spi_probe(struct platform_device *pdev)
+@@ -1107,22 +1121,40 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		goto err_put_master;
  	}
  
@@ -127,7 +119,7 @@
  
  	ret = devm_spi_register_master(&pdev->dev, master);
  	if (ret) {
-@@ -1201,8 +1233,11 @@ static int mtk_spi_suspend(struct device *dev)
+@@ -1202,8 +1234,11 @@ static int mtk_spi_suspend(struct device *dev)
  	if (ret)
  		return ret;
  
@@ -140,7 +132,7 @@
  
  	return ret;
  }
-@@ -1214,6 +1249,14 @@ static int mtk_spi_resume(struct device *dev)
+@@ -1215,6 +1250,14 @@ static int mtk_spi_resume(struct device *dev)
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
  
  	if (!pm_runtime_suspended(dev)) {
@@ -155,7 +147,7 @@
  		ret = clk_prepare_enable(mdata->spi_clk);
  		if (ret < 0) {
  			dev_err(dev, "failed to enable spi_clk (%d)\n", ret);
-@@ -1222,8 +1265,11 @@ static int mtk_spi_resume(struct device *dev)
+@@ -1223,8 +1266,11 @@ static int mtk_spi_resume(struct device *dev)
  	}
  
  	ret = spi_master_resume(master);
@@ -168,7 +160,7 @@
  
  	return ret;
  }
-@@ -1237,6 +1283,9 @@ static int mtk_spi_runtime_suspend(struct device *dev)
+@@ -1238,6 +1284,9 @@ static int mtk_spi_runtime_suspend(struct device *dev)
  
  	clk_disable_unprepare(mdata->spi_clk);
  
@@ -178,7 +170,7 @@
  	return 0;
  }
  
-@@ -1246,6 +1295,14 @@ static int mtk_spi_runtime_resume(struct device *dev)
+@@ -1247,6 +1296,14 @@ static int mtk_spi_runtime_resume(struct device *dev)
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
  	int ret;
  
@@ -194,5 +186,5 @@
  	if (ret < 0) {
  		dev_err(dev, "failed to enable spi_clk (%d)\n", ret);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9011-Modify-tick_delay-for-spi-work-safety.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2370-Modify-tick_delay-for-spi-work-safety.patch
similarity index 64%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9011-Modify-tick_delay-for-spi-work-safety.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2370-Modify-tick_delay-for-spi-work-safety.patch
index dd73f82..7adee7d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9011-Modify-tick_delay-for-spi-work-safety.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2370-Modify-tick_delay-for-spi-work-safety.patch
@@ -1,14 +1,15 @@
-From 02205bef8a645d4374d2869e3a5a5a1d7c2e693a Mon Sep 17 00:00:00 2001
-From: Qii Wang <qii.wang@mediatek.com>
-Date: Sat, 14 May 2022 14:18:13 +0800
-Subject: [PATCH] [Modify tick_delay for spi work safety]
+From adcc9739e6457df20339161299cf267de9699a2e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:20 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2370-Modify-tick_delay-for-spi-work-safety.patch]
 
 ---
  drivers/spi/spi-mt65xx.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index bef03bd8c..c19e2d4d7 100644
+index 7c3ee3381..83a2417a8 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -195,7 +195,7 @@ static const struct mtk_spi_compatible mt8183_compat = {
@@ -21,5 +22,5 @@
  
  static const struct of_device_id mtk_spi_of_match[] = {
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2371-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
similarity index 92%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2371-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
index d64f376..47611e5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2371-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
@@ -1,10 +1,9 @@
-From 45ec6dfcc5f48127d5bd440fb615bbf48f3fc9c1 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:29:51 +0800
-Subject: [PATCH] drivers: spi-mt65xx: Move chip_config to driver's private
- data
+From 8fc345d6238b0fb81f6737d21ca9d7efb1dd1489 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:20 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2371-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
  drivers/spi/spi-mt65xx.c                 | 31 +++++++++++-------------
  include/linux/platform_data/spi-mt65xx.h | 17 -------------
@@ -12,7 +11,7 @@
  delete mode 100644 include/linux/platform_data/spi-mt65xx.h
 
 diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index c19e2d4d7..0afd00891 100644
+index 83a2417a8..32a0b0264 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -14,7 +14,6 @@
@@ -138,5 +137,5 @@
 -};
 -#endif
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2372-drivers-spi-Add-support-for-dynamic-calibration.patch
similarity index 87%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2372-drivers-spi-Add-support-for-dynamic-calibration.patch
index 750c87b..d438084 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2372-drivers-spi-Add-support-for-dynamic-calibration.patch
@@ -1,17 +1,19 @@
-From a84c53fce4ccd67c147dcbb2dcf4fdeceab05981 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:35:52 +0800
-Subject: [PATCH] drivers: spi: Add support for dynamic calibration
+From a7d7d3c4d6a949135a34dff1e987a52de9f227b7 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:21 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2372-drivers-spi-Add-support-for-dynamic-calibration.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
- drivers/spi/spi.c       | 137 ++++++++++++++++++++++++++++++++++++++++
+ drivers/spi/spi.c       | 141 ++++++++++++++++++++++++++++++++++++++++
  include/linux/spi/spi.h |  42 ++++++++++++
- 2 files changed, 179 insertions(+)
+ 2 files changed, 183 insertions(+)
 
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index e562735a3..28bad4a8b 100644
 --- a/drivers/spi/spi.c
 +++ b/drivers/spi/spi.c
-@@ -1109,6 +1109,74 @@ static int spi_transfer_wait(struct spi_
+@@ -1109,6 +1109,74 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
  	return 0;
  }
  
@@ -86,7 +88,7 @@
  static void _spi_transfer_delay_ns(u32 ns)
  {
  	if (!ns)
-@@ -1720,6 +1788,75 @@ void spi_flush_queue(struct spi_controll
+@@ -1720,6 +1788,75 @@ void spi_flush_queue(struct spi_controller *ctlr)
  /*-------------------------------------------------------------------------*/
  
  #if defined(CONFIG_OF)
@@ -162,7 +164,7 @@
  static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
  			   struct device_node *nc)
  {
-@@ -1841,6 +1978,10 @@ of_register_spi_device(struct spi_contro
+@@ -1841,6 +1978,10 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
  	if (rc)
  		goto err_out;
  
@@ -173,6 +175,8 @@
  	/* Store a pointer to the node in the device structure */
  	of_node_get(nc);
  	spi->dev.of_node = nc;
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index 7067f85ce..5330cd9b0 100644
 --- a/include/linux/spi/spi.h
 +++ b/include/linux/spi/spi.h
 @@ -264,6 +264,40 @@ struct spi_driver {
@@ -228,7 +232,7 @@
  	int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
  };
  
-@@ -1369,6 +1408,9 @@ spi_register_board_info(struct spi_board
+@@ -1369,6 +1408,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
  	{ return 0; }
  #endif
  
@@ -238,3 +242,6 @@
  /* If you're hotplugging an adapter with devices (parport, usb, etc)
   * use spi_new_device() to describe each device.  You can also call
   * spi_unregister_device() to start making that device vanish, but
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2373-drivers-spi-mem-Add-spi-calibration-hook.patch
similarity index 82%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2373-drivers-spi-mem-Add-spi-calibration-hook.patch
index dcea7de..c16f87e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2373-drivers-spi-mem-Add-spi-calibration-hook.patch
@@ -1,9 +1,9 @@
-From a4f235c3a3c4d25aa6a4417ce64831ca0b38c324 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:37:55 +0800
-Subject: [PATCH] drivers: spi-mem: Add spi calibration hook
+From 945b61ae2d00d59eacebb70496ce9bc530767929 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:21 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2373-drivers-spi-mem-Add-spi-calibration-hook.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
  drivers/spi/spi-mem.c       | 8 ++++++++
  include/linux/spi/spi-mem.h | 4 ++++
@@ -44,5 +44,5 @@
  
  struct spi_mem_dirmap_desc *
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2374-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
similarity index 78%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2374-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
index 2c51aa9..f39b229 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2374-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
@@ -1,15 +1,15 @@
-From ac9ed3898b80a81ce220a682749767ef189094a8 Mon Sep 17 00:00:00 2001
-From: "SkyLake.Huang" <skylake.huang@mediatek.com>
-Date: Thu, 23 Jun 2022 18:39:03 +0800
-Subject: [PATCH] drivers: spi-mt65xx: Add controller's calibration paramter
+From 6411311c9df3bce87ad46650053eb52cf12be889 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:21 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2374-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch]
 
-Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
 ---
  drivers/spi/spi-mt65xx.c | 17 +++++++++++++++++
  1 file changed, 17 insertions(+)
 
 diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
-index 0afd00891..1b272d15c 100644
+index 32a0b0264..2034d1979 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -727,6 +727,21 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
@@ -44,5 +44,5 @@
  	if (!of_id) {
  		dev_err(&pdev->dev, "failed to probe of_node\n");
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9102-spi-update-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2375-spi-update-driver.patch
similarity index 91%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9102-spi-update-driver.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2375-spi-update-driver.patch
index 4900733..48e7187 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9102-spi-update-driver.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2375-spi-update-driver.patch
@@ -1,3 +1,14 @@
+From f8707b14c517f9402456c3c1e98f64d0eb8a4af5 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:21 +0800
+Subject: [PATCH] [spi-and-storage][999-2375-spi-update-driver.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 414 ++++++++++++++++++++++-----------------
+ 1 file changed, 231 insertions(+), 183 deletions(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 2034d1979..b80f8dcd9 100644
 --- a/drivers/spi/spi-mt65xx.c
 +++ b/drivers/spi/spi-mt65xx.c
 @@ -12,7 +12,7 @@
@@ -71,7 +82,7 @@
  	struct completion spimem_done;
  	bool use_spimem;
  	struct device *dev;
-@@ -154,21 +152,10 @@ static const struct mtk_spi_compatible m
+@@ -154,21 +152,10 @@ static const struct mtk_spi_compatible mt2712_compat = {
  	.must_tx = true,
  };
  
@@ -94,7 +105,7 @@
  };
  
  static const struct mtk_spi_compatible mt6765_compat = {
-@@ -194,13 +181,25 @@ static const struct mtk_spi_compatible m
+@@ -194,13 +181,25 @@ static const struct mtk_spi_compatible mt8183_compat = {
  	.enhance_timing = true,
  };
  
@@ -122,7 +133,7 @@
  	{ .compatible = "mediatek,mt2701-spi",
  		.data = (void *)&mtk_common_compat,
  	},
-@@ -228,6 +227,12 @@ static const struct of_device_id mtk_spi
+@@ -228,6 +227,12 @@ static const struct of_device_id mtk_spi_of_match[] = {
  	{ .compatible = "mediatek,mt8183-spi",
  		.data = (void *)&mt8183_compat,
  	},
@@ -135,7 +146,7 @@
  	{}
  };
  MODULE_DEVICE_TABLE(of, mtk_spi_of_match);
-@@ -256,27 +261,30 @@ static int mtk_spi_hw_init(struct spi_ma
+@@ -256,27 +261,30 @@ static int mtk_spi_hw_init(struct spi_master *master,
  	cpha = spi->mode & SPI_CPHA ? 1 : 0;
  	cpol = spi->mode & SPI_CPOL ? 1 : 0;
  
@@ -176,7 +187,7 @@
  	reg_val = readl(mdata->base + SPI_CMD_REG);
  	if (mdata->dev_comp->ipm_design) {
  		/* SPI transfer without idle time until packet length done */
-@@ -375,12 +383,11 @@ static void mtk_spi_set_cs(struct spi_de
+@@ -375,12 +383,11 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
  static void mtk_spi_prepare_transfer(struct spi_master *master,
  				     u32 speed_hz)
  {
@@ -192,7 +203,7 @@
  	else
  		div = 1;
  
-@@ -388,13 +395,19 @@ static void mtk_spi_prepare_transfer(str
+@@ -388,13 +395,19 @@ static void mtk_spi_prepare_transfer(struct spi_master *master,
  	cs_time = sck_time * 2;
  
  	if (mdata->dev_comp->enhance_timing) {
@@ -214,7 +225,7 @@
  		reg_val |= (((cs_time - 1) & 0xffff)
  			   << SPI_ADJUST_CFG0_CS_SETUP_OFFSET);
  		writel(reg_val, mdata->base + SPI_CFG0_REG);
-@@ -453,14 +466,17 @@ static void mtk_spi_enable_transfer(stru
+@@ -453,14 +466,17 @@ static void mtk_spi_enable_transfer(struct spi_master *master)
  	writel(cmd, mdata->base + SPI_CMD_REG);
  }
  
@@ -238,7 +249,7 @@
  
  	return mult_delta;
  }
-@@ -472,22 +488,22 @@ static void mtk_spi_update_mdata_len(str
+@@ -472,22 +488,22 @@ static void mtk_spi_update_mdata_len(struct spi_master *master)
  
  	if (mdata->tx_sgl_len && mdata->rx_sgl_len) {
  		if (mdata->tx_sgl_len > mdata->rx_sgl_len) {
@@ -265,7 +276,7 @@
  		mdata->xfer_len = mdata->rx_sgl_len - mult_delta;
  		mdata->rx_sgl_len = mult_delta;
  	}
-@@ -598,6 +614,19 @@ static int mtk_spi_transfer_one(struct s
+@@ -598,6 +614,19 @@ static int mtk_spi_transfer_one(struct spi_master *master,
  				struct spi_device *spi,
  				struct spi_transfer *xfer)
  {
@@ -285,7 +296,7 @@
  	if (master->can_dma(master, spi, xfer))
  		return mtk_spi_dma_transfer(master, spi, xfer);
  	else
-@@ -618,8 +647,9 @@ static int mtk_spi_setup(struct spi_devi
+@@ -618,8 +647,9 @@ static int mtk_spi_setup(struct spi_device *spi)
  {
  	struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
  
@@ -297,7 +308,7 @@
  
  	return 0;
  }
-@@ -747,9 +777,6 @@ static int mtk_spi_mem_adjust_op_size(st
+@@ -747,9 +777,6 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
  {
  	int opcode_len;
  
@@ -307,7 +318,7 @@
  	if (op->data.dir != SPI_MEM_NO_DATA) {
  		opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
  		if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
-@@ -765,8 +792,7 @@ static int mtk_spi_mem_adjust_op_size(st
+@@ -765,8 +792,7 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
  static bool mtk_spi_mem_supports_op(struct spi_mem *mem,
  				     const struct spi_mem_op *op)
  {
@@ -317,7 +328,7 @@
  		return false;
  
  	if (op->addr.nbytes && op->dummy.nbytes &&
-@@ -814,13 +840,18 @@ static int mtk_spi_transfer_wait(struct
+@@ -814,13 +840,18 @@ static int mtk_spi_transfer_wait(struct spi_mem *mem,
  				 const struct spi_mem_op *op)
  {
  	struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master);
@@ -340,7 +351,7 @@
  	ms += ms + 1000; /* 1s tolerance */
  
  	if (ms > UINT_MAX)
-@@ -839,9 +870,8 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -839,9 +870,8 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  				const struct spi_mem_op *op)
  {
  	struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master);
@@ -352,7 +363,7 @@
  	int ret = 0;
  
  	mdata->use_spimem = true;
-@@ -887,9 +917,11 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -887,9 +917,11 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  		 op->dummy.buswidth == 4 ||
  		 op->data.buswidth == 4)
  		nio = 4;
@@ -365,7 +376,7 @@
  
  	reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN;
  	if (op->data.dir == SPI_MEM_DATA_IN)
-@@ -902,11 +934,13 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -902,11 +934,13 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  	if (op->data.dir == SPI_MEM_DATA_OUT)
  		tx_size += op->data.nbytes;
  
@@ -381,7 +392,7 @@
  
  	tx_tmp_buf[0] = op->cmd.opcode;
  
-@@ -937,12 +971,15 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -937,12 +971,15 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  
  	if (op->data.dir == SPI_MEM_DATA_IN) {
  		if(!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
@@ -402,7 +413,7 @@
  
  		mdata->rx_dma = dma_map_single(mdata->dev,
  						   rx_tmp_buf,
-@@ -950,7 +987,7 @@ static int mtk_spi_mem_exec_op(struct sp
+@@ -950,7 +987,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem,
  						   DMA_FROM_DEVICE);
  		if (dma_mapping_error(mdata->dev, mdata->rx_dma)) {
  			ret = -ENOMEM;
@@ -428,7 +439,7 @@
  unmap_tx_dma:
  	dma_unmap_single(mdata->dev, mdata->tx_dma,
  			 tx_size, DMA_TO_DEVICE);
-@@ -1003,19 +1042,19 @@ static const struct spi_controller_mem_o
+@@ -1003,19 +1042,19 @@ static const struct spi_controller_mem_ops mtk_spi_mem_ops = {
  
  static int mtk_spi_probe(struct platform_device *pdev)
  {
@@ -452,7 +463,7 @@
  	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
  
  	master->set_cs = mtk_spi_set_cs;
-@@ -1023,23 +1062,16 @@ static int mtk_spi_probe(struct platform
+@@ -1023,23 +1062,16 @@ static int mtk_spi_probe(struct platform_device *pdev)
  	master->transfer_one = mtk_spi_transfer_one;
  	master->can_dma = mtk_spi_can_dma;
  	master->setup = mtk_spi_setup;
@@ -478,7 +489,7 @@
  
  	if (mdata->dev_comp->enhance_timing)
  		master->mode_bits |= SPI_CS_HIGH;
-@@ -1050,27 +1082,23 @@ static int mtk_spi_probe(struct platform
+@@ -1050,27 +1082,23 @@ static int mtk_spi_probe(struct platform_device *pdev)
  	if (mdata->dev_comp->ipm_design)
  		master->mode_bits |= SPI_LOOP;
  
@@ -511,7 +522,7 @@
  						    sizeof(u32), GFP_KERNEL);
  		if (!mdata->pad_sel) {
  			ret = -ENOMEM;
-@@ -1078,11 +1106,11 @@ static int mtk_spi_probe(struct platform
+@@ -1078,11 +1106,11 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		}
  
  		for (i = 0; i < mdata->pad_num; i++) {
@@ -525,7 +536,7 @@
  					i, mdata->pad_sel[i]);
  				ret = -EINVAL;
  				goto err_put_master;
-@@ -1103,122 +1131,118 @@ static int mtk_spi_probe(struct platform
+@@ -1103,122 +1131,118 @@ static int mtk_spi_probe(struct platform_device *pdev)
  		goto err_put_master;
  	}
  
@@ -702,7 +713,7 @@
  err_put_master:
  	spi_master_put(master);
  
-@@ -1229,11 +1253,22 @@ static int mtk_spi_remove(struct platfor
+@@ -1229,11 +1253,22 @@ static int mtk_spi_remove(struct platform_device *pdev)
  {
  	struct spi_master *master = platform_get_drvdata(pdev);
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
@@ -726,7 +737,7 @@
  	return 0;
  }
  
-@@ -1250,8 +1285,7 @@ static int mtk_spi_suspend(struct device
+@@ -1250,8 +1285,7 @@ static int mtk_spi_suspend(struct device *dev)
  
  	if (!pm_runtime_suspended(dev)) {
  		clk_disable_unprepare(mdata->spi_clk);
@@ -736,7 +747,7 @@
  	}
  
  	return ret;
-@@ -1264,26 +1298,24 @@ static int mtk_spi_resume(struct device
+@@ -1264,26 +1298,24 @@ static int mtk_spi_resume(struct device *dev)
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
  
  	if (!pm_runtime_suspended(dev)) {
@@ -771,7 +782,7 @@
  	}
  
  	return ret;
-@@ -1296,10 +1328,13 @@ static int mtk_spi_runtime_suspend(struc
+@@ -1296,10 +1328,13 @@ static int mtk_spi_runtime_suspend(struct device *dev)
  	struct spi_master *master = dev_get_drvdata(dev);
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
  
@@ -788,7 +799,7 @@
  
  	return 0;
  }
-@@ -1310,18 +1345,31 @@ static int mtk_spi_runtime_resume(struct
+@@ -1310,18 +1345,31 @@ static int mtk_spi_runtime_resume(struct device *dev)
  	struct mtk_spi *mdata = spi_master_get_devdata(master);
  	int ret;
  
@@ -827,3 +838,6 @@
  	}
  
  	return 0;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2376-drivers-spi-mt65xx-add-dts-buswidth-flow.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2376-drivers-spi-mt65xx-add-dts-buswidth-flow.patch
new file mode 100644
index 0000000..ffe6003
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2376-drivers-spi-mt65xx-add-dts-buswidth-flow.patch
@@ -0,0 +1,26 @@
+From 89740f80939ddd9b73648da2a97c8f31ae16050a Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:22 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2376-drivers-spi-mt65xx-add-dts-buswidth-flow.patch]
+
+---
+ drivers/spi/spi-mt65xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index b80f8dcd9..ac95e26c1 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -1080,7 +1080,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
+ 		master->flags = SPI_MASTER_MUST_TX;
+ 
+ 	if (mdata->dev_comp->ipm_design)
+-		master->mode_bits |= SPI_LOOP;
++		master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
+ 
+ 	if (mdata->dev_comp->ipm_design) {
+ 		mdata->dev = dev;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0322-fix-dirty-race-between-do_tmpfile.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
similarity index 88%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0322-fix-dirty-race-between-do_tmpfile.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
index 94ce9bd..63943f8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0322-fix-dirty-race-between-do_tmpfile.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
@@ -1,4 +1,15 @@
+From d08d34636d1384d5ddb141e0bb72afa591c12118 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:22 +0800
+Subject: [PATCH] 
+ [spi-and-storage][999-2380-fix-dirty-race-between-do_tmpfile.patch]
+
+---
+ fs/ubifs/dir.c | 60 +++++++++++++++++++++++++-------------------------
+ 1 file changed, 30 insertions(+), 30 deletions(-)
+
 diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
+index 332c0b02a..97b231c43 100644
 --- a/fs/ubifs/dir.c
 +++ b/fs/ubifs/dir.c
 @@ -356,6 +356,32 @@ out_budg:
@@ -98,3 +109,6 @@
  static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
  		      struct dentry *dentry)
  {
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2500-cpufreq-add-the-missing-platform-driver-unregister.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2500-cpufreq-add-the-missing-platform-driver-unregister.patch
new file mode 100644
index 0000000..b03956f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2500-cpufreq-add-the-missing-platform-driver-unregister.patch
@@ -0,0 +1,25 @@
+From 074bd5464b2e05ad5c8ed9ba0442a8abdfd4e2fc Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:22 +0800
+Subject: [PATCH] 
+ [adv-feature][999-2500-cpufreq-add-the-missing-platform-driver-unregister.patch]
+
+---
+ drivers/cpufreq/mediatek-cpufreq.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 927ebc582..03bb7b58d 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -573,6 +573,7 @@ static int __init mtk_cpufreq_driver_init(void)
+ 	pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
+ 	if (IS_ERR(pdev)) {
+ 		pr_err("failed to register mtk-cpufreq platform device\n");
++		platform_driver_unregister(&mtk_cpufreq_platdrv);
+ 		return PTR_ERR(pdev);
+ 	}
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2501-cpufreq-Enable-clocks-and-regulators.patch
similarity index 85%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2501-cpufreq-Enable-clocks-and-regulators.patch
index 2fa9359..ca84955 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2501-cpufreq-Enable-clocks-and-regulators.patch
@@ -1,5 +1,15 @@
+From 31b16ccb455139f23e4989c0795564350774c8c6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:22 +0800
+Subject: [PATCH] 
+ [adv-feature][999-2501-cpufreq-Enable-clocks-and-regulators.patch]
+
+---
+ drivers/cpufreq/mediatek-cpufreq.c | 41 +++++++++++++++++++++++++++---
+ 1 file changed, 37 insertions(+), 4 deletions(-)
+
 diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
-index 03bb7b5..010a947 100644
+index 03bb7b58d..010a947a6 100644
 --- a/drivers/cpufreq/mediatek-cpufreq.c
 +++ b/drivers/cpufreq/mediatek-cpufreq.c
 @@ -351,6 +351,12 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
@@ -86,3 +96,6 @@
  
  	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
  }
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2502-cpufreq-add-mt7988a-spim-snand-support.patch
similarity index 94%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2502-cpufreq-add-mt7988a-spim-snand-support.patch
index ee87f4e..b40509d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2502-cpufreq-add-mt7988a-spim-snand-support.patch
@@ -1,5 +1,15 @@
+From 8abbdaf99bd93b9009482e49c94455d5c10a29f6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:23 +0800
+Subject: [PATCH] 
+ [adv-feature][999-2502-cpufreq-add-mt7988a-spim-snand-support.patch]
+
+---
+ drivers/cpufreq/mediatek-cpufreq.c | 83 +++++++++++++++++++++++++++++-
+ 1 file changed, 81 insertions(+), 2 deletions(-)
+
 diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
-index 010a947..291f629 100644
+index 010a947a6..b23b6d2b4 100644
 --- a/drivers/cpufreq/mediatek-cpufreq.c
 +++ b/drivers/cpufreq/mediatek-cpufreq.c
 @@ -38,6 +38,7 @@ struct mtk_cpu_dvfs_info {
@@ -210,3 +220,6 @@
  
  	{ }
  };
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch
similarity index 78%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch
index aa31f22..032d163 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch
@@ -1,5 +1,15 @@
+From 96af4d1381b43bafba252d38c2a344f1011de638 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:23 +0800
+Subject: [PATCH] 
+ [adv-feature][999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch]
+
+---
+ drivers/cpufreq/mediatek-cpufreq.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
 diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
-index b23b6d2..147a224 100644
+index b23b6d2b4..c22945100 100644
 --- a/drivers/cpufreq/mediatek-cpufreq.c
 +++ b/drivers/cpufreq/mediatek-cpufreq.c
 @@ -15,6 +15,7 @@
@@ -45,3 +55,6 @@
  	ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
  	if (ret) {
  		pr_err("failed to init cpufreq table for cpu%d: %d\n",
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2530-add-pmic-config.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2530-add-pmic-config.patch
index f5384f3..0194261 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2530-add-pmic-config.patch
@@ -1,5 +1,15 @@
+From 4ff5fd6b2d7df7b572bce364d6a1853665e378ac Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:23 +0800
+Subject: [PATCH] [adv-feature][999-2530-add-pmic-config.patch]
+
+---
+ drivers/regulator/Kconfig  | 10 ++++++++++
+ drivers/regulator/Makefile |  1 +
+ 2 files changed, 11 insertions(+)
+
 diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
-index 3ee6353..2e393a7 100644
+index 3ee63531f..5c573ced5 100644
 --- a/drivers/regulator/Kconfig
 +++ b/drivers/regulator/Kconfig
 @@ -798,6 +798,16 @@ config REGULATOR_RT5033
@@ -20,7 +30,7 @@
  	tristate "Samsung S2MPA01 voltage regulator"
  	depends on MFD_SEC_CORE
 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
-index 2210ba5..bf75b77 100644
+index 2210ba56f..bf75b7755 100644
 --- a/drivers/regulator/Makefile
 +++ b/drivers/regulator/Makefile
 @@ -100,6 +100,7 @@ obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -32,5 +42,5 @@
  obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
  obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch
new file mode 100644
index 0000000..350e7d3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch
@@ -0,0 +1,40 @@
+From 7be8614176dc79bc242a12b7669f330058e36df6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:24 +0800
+Subject: [PATCH] [adv-feature][999-2550-dual-image-mount-rootfs.patch]
+
+---
+ init/do_mounts.c    | 3 ++-
+ kernel/boot_param.c | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/init/do_mounts.c b/init/do_mounts.c
+index cd5fca8aa..2dfc0dac7 100644
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -576,7 +576,8 @@ void __init mount_root(void)
+ 	}
+ #endif
+ #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+-	if (!mount_ubi_rootfs())
++	extern bool dual_boot;
++	if (!dual_boot && !mount_ubi_rootfs())
+ 		return;
+ #endif
+ #ifdef CONFIG_BLOCK
+diff --git a/kernel/boot_param.c b/kernel/boot_param.c
+index 3dfe828bc..cc0b2b8b0 100644
+--- a/kernel/boot_param.c
++++ b/kernel/boot_param.c
+@@ -10,7 +10,7 @@
+ 
+ #define BOOT_PARAM_STR_MAX_LEN			256
+ 
+-static bool dual_boot;
++bool dual_boot;
+ module_param(dual_boot, bool, 0444);
+ 
+ static bool no_split_rootfs_data;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1015-pcie-add-pcie-gen3-upstream-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2600-pcie-add-pcie-gen3-upstream-driver.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1015-pcie-add-pcie-gen3-upstream-driver.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2600-pcie-add-pcie-gen3-upstream-driver.patch
index 4b99d9d..6e5b96a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1015-pcie-add-pcie-gen3-upstream-driver.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2600-pcie-add-pcie-gen3-upstream-driver.patch
@@ -1,5 +1,16 @@
+From 99a6452c7481de2f1a36699dd60361c49602cc77 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:24 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2600-pcie-add-pcie-gen3-upstream-driver.patch]
+
+---
+ drivers/pci/controller/Kconfig  | 13 +++++++++++++
+ drivers/pci/controller/Makefile |  1 +
+ 2 files changed, 14 insertions(+)
+
 diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
-index 70e0782..67988f8 100644
+index 70e078238..67988f868 100644
 --- a/drivers/pci/controller/Kconfig
 +++ b/drivers/pci/controller/Kconfig
 @@ -241,6 +241,19 @@ config PCIE_MEDIATEK
@@ -23,7 +34,7 @@
  	bool "Mobiveil AXI PCIe controller"
  	depends on ARCH_ZYNQMP || COMPILE_TEST
 diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
-index a2a22c9..54a496a 100644
+index a2a22c9d9..54a496a68 100644
 --- a/drivers/pci/controller/Makefile
 +++ b/drivers/pci/controller/Makefile
 @@ -27,6 +27,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
@@ -34,3 +45,6 @@
  obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
  obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
  obj-$(CONFIG_VMD) += vmd.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1024-pcie-add-multi-MSI-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch
similarity index 75%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1024-pcie-add-multi-MSI-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch
index 5cf486c..80ce145 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1024-pcie-add-multi-MSI-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch
@@ -1,8 +1,17 @@
+From f001395855db2d04f499a2e2936f1d54dcaab225 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:24 +0800
+Subject: [PATCH] [high-speed-io][999-2601-pcie-add-multi-MSI-support.patch]
+
+---
+ drivers/pci/controller/pcie-mediatek.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
 diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
-index 2a54fa7a3..132b3204c 100644
+index db3672917..44a046005 100644
 --- a/drivers/pci/controller/pcie-mediatek.c
 +++ b/drivers/pci/controller/pcie-mediatek.c
-@@ -446,24 +446,24 @@ static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int vir
+@@ -440,24 +440,24 @@ static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int vir
  				     unsigned int nr_irqs, void *args)
  {
  	struct mtk_pcie_port *port = domain->host_data;
@@ -36,7 +45,7 @@
  
  	return 0;
  }
-@@ -501,7 +501,7 @@ static struct irq_chip mtk_msi_irq_chip = {
+@@ -495,7 +495,7 @@ static struct irq_chip mtk_msi_irq_chip = {
  
  static struct msi_domain_info mtk_msi_domain_info = {
  	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
@@ -45,7 +54,7 @@
  	.chip	= &mtk_msi_irq_chip,
  };
  
-@@ -633,14 +633,14 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
+@@ -627,14 +627,14 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
  		if (status & MSI_STATUS){
  			unsigned long imsi_status;
  
@@ -62,3 +71,6 @@
  		}
  	}
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8000-PATCH-1-4-tphy-support-type-switch-by-pericfg.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2610-tphy-support-type-switch-by-pericfg.patch
similarity index 77%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8000-PATCH-1-4-tphy-support-type-switch-by-pericfg.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2610-tphy-support-type-switch-by-pericfg.patch
index 032ef35..da92a39 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8000-PATCH-1-4-tphy-support-type-switch-by-pericfg.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2610-tphy-support-type-switch-by-pericfg.patch
@@ -1,21 +1,15 @@
-From 34687407776d46f08926b91f118adc484c4ac231 Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Fri, 17 Sep 2021 15:56:53 +0800
-Subject: [PATCH 1/8] phy: phy-mtk-tphy: support type switch by pericfg
+From 3ef64d448a36853279de5324f9bf00041b9f3ce5 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:25 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2610-tphy-support-type-switch-by-pericfg.patch]
 
-Add support type switch between USB3, PCIe, SATA and SGMII by
-pericfg register, this is used to take the place of efuse or
-jumper.
-
-Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Signed-off-by: Vinod Koul <vkoul@kernel.org>
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/phy/mediatek/phy-mtk-tphy.c | 83 ++++++++++++++++++++++++++++-
  1 file changed, 81 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index cb2ed3b25068..a59fe65f69e5 100644
+index d1ecf0880..c6e073401 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
 @@ -10,6 +10,7 @@
@@ -26,9 +20,9 @@
  #include <linux/module.h>
  #include <linux/of_address.h>
  #include <linux/of_device.h>
-@@ -263,6 +264,14 @@
- #define RG_CDR_BIRLTD0_GEN3_MSK		GENMASK(4, 0)
- #define RG_CDR_BIRLTD0_GEN3_VAL(x)	(0x1f & (x))
+@@ -268,6 +269,14 @@
+ #define HIF_SYSCFG1			0x14
+ #define HIF_SYSCFG1_PHY2_MASK		(0x3 << 20)
  
 +/* PHY switch between pcie/usb3/sgmii/sata */
 +#define USB_PHY_SWITCH_CTRL	0x0
@@ -41,7 +35,7 @@
  enum mtk_phy_version {
  	MTK_PHY_V1 = 1,
  	MTK_PHY_V2,
-@@ -296,7 +305,10 @@ struct mtk_phy_instance {
+@@ -301,7 +310,10 @@ struct mtk_phy_instance {
  	};
  	struct clk *ref_clk;	/* reference clock of anolog phy */
  	u32 index;
@@ -53,7 +47,7 @@
  	int eye_src;
  	int eye_vrt;
  	int eye_term;
-@@ -890,6 +902,64 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
+@@ -900,6 +912,64 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
  	}
  }
  
@@ -118,7 +112,7 @@
  static int mtk_phy_init(struct phy *phy)
  {
  	struct mtk_phy_instance *instance = phy_get_drvdata(phy);
-@@ -922,6 +992,9 @@ static int mtk_phy_init(struct phy *phy)
+@@ -932,6 +1002,9 @@ static int mtk_phy_init(struct phy *phy)
  	case PHY_TYPE_SATA:
  		sata_phy_instance_init(tphy, instance);
  		break;
@@ -128,7 +122,7 @@
  	default:
  		dev_err(tphy->dev, "incompatible PHY type\n");
  		return -EINVAL;
-@@ -1010,7 +1083,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+@@ -1020,7 +1093,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
  	if (!(instance->type == PHY_TYPE_USB2 ||
  	      instance->type == PHY_TYPE_USB3 ||
  	      instance->type == PHY_TYPE_PCIE ||
@@ -138,7 +132,7 @@
  		dev_err(dev, "unsupported device type: %d\n", instance->type);
  		return ERR_PTR(-EINVAL);
  	}
-@@ -1025,6 +1099,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+@@ -1035,6 +1109,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
  	}
  
  	phy_parse_property(tphy, instance);
@@ -146,7 +140,7 @@
  
  	return instance->phy;
  }
-@@ -1163,6 +1238,10 @@ static int mtk_tphy_probe(struct platform_device *pdev)
+@@ -1183,6 +1258,10 @@ static int mtk_tphy_probe(struct platform_device *pdev)
  			retval = PTR_ERR(instance->ref_clk);
  			goto put_child;
  		}
@@ -158,5 +152,5 @@
  
  	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8006-phy-phy-mtk-tphy-add-support-efuse-setting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2611-phy-phy-mtk-tphy-add-support-efuse-setting.patch
similarity index 88%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8006-phy-phy-mtk-tphy-add-support-efuse-setting.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2611-phy-phy-mtk-tphy-add-support-efuse-setting.patch
index 05eb738..1f958e8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8006-phy-phy-mtk-tphy-add-support-efuse-setting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2611-phy-phy-mtk-tphy-add-support-efuse-setting.patch
@@ -1,21 +1,15 @@
-From a2eaa93a5887ddd20af0373244481139627d0d77 Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Mon, 8 Nov 2021 14:51:38 +0800
-Subject: [PATCH 2/8] phy: phy-mtk-tphy: add support efuse setting
+From 004157ce74543694981c461e95ac0cc1fa8721d7 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:25 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2611-phy-phy-mtk-tphy-add-support-efuse-setting.patch]
 
-Due to some SoCs have a bit shift issue that will drop a bit for usb3
-phy or pcie phy, fix it by adding software efuse reading and setting,
-but only support it optionally for versoin.
-
-Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Change-Id: Ibf88868668b3889f18c7930531981400cac732f1
 ---
  drivers/phy/mediatek/phy-mtk-tphy.c | 195 ++++++++++++++++++++++++++++
  1 file changed, 195 insertions(+)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index a59fe65f69e5..ce2731b2f5ff 100644
+index c6e073401..fcf8c845f 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
 @@ -12,6 +12,7 @@
@@ -26,7 +20,7 @@
  #include <linux/of_address.h>
  #include <linux/of_device.h>
  #include <linux/phy/phy.h>
-@@ -39,11 +40,16 @@
+@@ -41,11 +42,16 @@
  #define SSUSB_SIFSLV_V2_U3PHYD		0x200
  #define SSUSB_SIFSLV_V2_U3PHYA		0x400
  
@@ -43,7 +37,7 @@
  #define PA1_RG_VRT_SEL			GENMASK(14, 12)
  #define PA1_RG_VRT_SEL_VAL(x)	((0x7 & (x)) << 12)
  #define PA1_RG_TERM_SEL		GENMASK(10, 8)
-@@ -115,6 +121,8 @@
+@@ -117,6 +123,8 @@
  #define P3C_RG_SWRST_U3_PHYD_FORCE_EN	BIT(24)
  
  #define U3P_U3_PHYA_REG0	0x000
@@ -52,7 +46,7 @@
  #define P3A_RG_CLKDRV_OFF		GENMASK(3, 2)
  #define P3A_RG_CLKDRV_OFF_VAL(x)	((0x3 & (x)) << 2)
  
-@@ -169,6 +177,25 @@
+@@ -171,6 +179,25 @@
  #define P3D_RG_FWAKE_TH		GENMASK(21, 16)
  #define P3D_RG_FWAKE_TH_VAL(x)	((0x3f & (x)) << 16)
  
@@ -78,7 +72,7 @@
  #define U3P_U3_PHYD_CDR1		0x05c
  #define P3D_RG_CDR_BIR_LTD1		GENMASK(28, 24)
  #define P3D_RG_CDR_BIR_LTD1_VAL(x)	((0x1f & (x)) << 24)
-@@ -275,11 +302,23 @@
+@@ -280,11 +307,23 @@
  enum mtk_phy_version {
  	MTK_PHY_V1 = 1,
  	MTK_PHY_V2,
@@ -102,7 +96,7 @@
  	enum mtk_phy_version version;
  };
  
-@@ -304,6 +343,10 @@ struct mtk_phy_instance {
+@@ -309,6 +348,10 @@ struct mtk_phy_instance {
  		struct u3phy_banks u3_banks;
  	};
  	struct clk *ref_clk;	/* reference clock of anolog phy */
@@ -113,7 +107,7 @@
  	u32 index;
  	u32 type;
  	struct regmap *type_sw;
-@@ -960,6 +1003,139 @@ static int phy_type_set(struct mtk_phy_instance *instance)
+@@ -970,6 +1013,139 @@ static int phy_type_set(struct mtk_phy_instance *instance)
  	return 0;
  }
  
@@ -253,7 +247,7 @@
  static int mtk_phy_init(struct phy *phy)
  {
  	struct mtk_phy_instance *instance = phy_get_drvdata(phy);
-@@ -978,6 +1154,8 @@ static int mtk_phy_init(struct phy *phy)
+@@ -988,6 +1164,8 @@ static int mtk_phy_init(struct phy *phy)
  		return ret;
  	}
  
@@ -262,7 +256,7 @@
  	switch (instance->type) {
  	case PHY_TYPE_USB2:
  		u2_phy_instance_init(tphy, instance);
-@@ -1062,6 +1240,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+@@ -1072,6 +1250,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
  	struct mtk_phy_instance *instance = NULL;
  	struct device_node *phy_np = args->np;
  	int index;
@@ -270,7 +264,7 @@
  
  	if (args->args_count != 1) {
  		dev_err(dev, "invalid number of cells in 'phy' property\n");
-@@ -1098,6 +1277,10 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+@@ -1108,6 +1287,10 @@ static struct phy *mtk_phy_xlate(struct device *dev,
  		return ERR_PTR(-EINVAL);
  	}
  
@@ -281,7 +275,7 @@
  	phy_parse_property(tphy, instance);
  	phy_type_set(instance);
  
-@@ -1120,14 +1303,26 @@ static const struct mtk_phy_pdata tphy_v1_pdata = {
+@@ -1130,14 +1313,26 @@ static const struct mtk_phy_pdata tphy_v1_pdata = {
  
  static const struct mtk_phy_pdata tphy_v2_pdata = {
  	.avoid_rx_sen_degradation = false,
@@ -309,5 +303,5 @@
  	{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
  	{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8007-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2612-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch
similarity index 88%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8007-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2612-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch
index 1c6711f..1a70ada 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8007-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2612-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch
@@ -1,21 +1,18 @@
-From 2abe803824f0331c42eb9853199d5f147cee3a06 Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Tue, 25 Jan 2022 16:50:47 +0800
-Subject: [PATCH 3/8] phy: phy-mtk-tphy: Add PCIe 2 lane efuse support
+From e63fdeaa652ad5fd8d7a591e346abe587fd9bede Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:25 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2612-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch]
 
-Add PCIe 2 lane efuse support in tphy driver.
-
-Signed-off-by: Jie Yang <jieyy.yang@mediatek.com>
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/phy/mediatek/phy-mtk-tphy.c | 140 ++++++++++++++++++++++++++++
  1 file changed, 140 insertions(+)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index ce2731b2f5ff..b855e759b0da 100644
+index fcf8c845f..6c07885be 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
-@@ -40,6 +40,15 @@
+@@ -42,6 +42,15 @@
  #define SSUSB_SIFSLV_V2_U3PHYD		0x200
  #define SSUSB_SIFSLV_V2_U3PHYA		0x400
  
@@ -31,7 +28,7 @@
  #define U3P_MISC_REG1		0x04
  #define MR1_EFUSE_AUTO_LOAD_DIS		BIT(6)
  
-@@ -303,6 +312,7 @@ enum mtk_phy_version {
+@@ -308,6 +317,7 @@ enum mtk_phy_version {
  	MTK_PHY_V1 = 1,
  	MTK_PHY_V2,
  	MTK_PHY_V3,
@@ -39,7 +36,7 @@
  };
  
  struct mtk_phy_pdata {
-@@ -347,6 +357,9 @@ struct mtk_phy_instance {
+@@ -352,6 +362,9 @@ struct mtk_phy_instance {
  	u32 efuse_intr;
  	u32 efuse_tx_imp;
  	u32 efuse_rx_imp;
@@ -49,7 +46,7 @@
  	u32 index;
  	u32 type;
  	struct regmap *type_sw;
-@@ -890,6 +903,36 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy,
+@@ -900,6 +913,36 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy,
  	}
  }
  
@@ -86,7 +83,7 @@
  static void phy_parse_property(struct mtk_tphy *tphy,
  				struct mtk_phy_instance *instance)
  {
-@@ -1072,6 +1115,40 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
+@@ -1082,6 +1125,40 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
  		dev_info(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n",
  			 instance->efuse_intr, instance->efuse_rx_imp,
  			 instance->efuse_tx_imp);
@@ -127,7 +124,7 @@
  		break;
  	default:
  		dev_err(dev, "no sw efuse for type %d\n", instance->type);
-@@ -1105,6 +1182,31 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1115,6 +1192,31 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  
  		break;
  	case PHY_TYPE_USB3:
@@ -159,7 +156,7 @@
  	case PHY_TYPE_PCIE:
  		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
  		tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS;
-@@ -1129,6 +1231,35 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1139,6 +1241,35 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  		pr_err("%s set efuse, tx_imp %x, rx_imp %x intr %x\n",
  			__func__, instance->efuse_tx_imp,
  			instance->efuse_rx_imp, instance->efuse_intr);
@@ -195,7 +192,7 @@
  		break;
  	default:
  		dev_warn(dev, "no sw efuse for type %d\n", instance->type);
-@@ -1272,6 +1403,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+@@ -1282,6 +1413,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
  		phy_v1_banks_init(tphy, instance);
  	} else if (tphy->pdata->version == MTK_PHY_V2) {
  		phy_v2_banks_init(tphy, instance);
@@ -204,7 +201,7 @@
  	} else {
  		dev_err(dev, "phy version is not supported\n");
  		return ERR_PTR(-EINVAL);
-@@ -1323,12 +1456,19 @@ static const struct mtk_phy_pdata mt8195_pdata = {
+@@ -1333,12 +1466,19 @@ static const struct mtk_phy_pdata mt8195_pdata = {
  	.version = MTK_PHY_V3,
  };
  
@@ -225,5 +222,5 @@
  };
  MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8008-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2613-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch
similarity index 81%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8008-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2613-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch
index e84ca6c..64e68c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8008-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2613-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch
@@ -1,21 +1,18 @@
-From 355e7f114a47819c3c6545a97ad308d627da5d1a Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Tue, 25 Jan 2022 19:03:34 +0800
-Subject: [PATCH 4/8] phy: phy-mtk-tphy: add auto-load-valid check mechanism
- support
+From 0e03f2c1ade35e8d40c87425414d0a6ccef0439c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:25 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2613-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch]
 
-add auto-load-valid check mechanism support
-
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/phy/mediatek/phy-mtk-tphy.c | 67 +++++++++++++++++++++++++++--
  1 file changed, 64 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index b855e759b0da..a5b17a1aed5c 100644
+index 6c07885be..149464f37 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
-@@ -354,9 +354,13 @@ struct mtk_phy_instance {
+@@ -359,9 +359,13 @@ struct mtk_phy_instance {
  	};
  	struct clk *ref_clk;	/* reference clock of anolog phy */
  	u32 efuse_sw_en;
@@ -29,7 +26,7 @@
  	u32 efuse_intr_ln1;
  	u32 efuse_tx_imp_ln1;
  	u32 efuse_rx_imp_ln1;
-@@ -1050,6 +1054,7 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
+@@ -1060,6 +1064,7 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
  {
  	struct device *dev = &instance->phy->dev;
  	int ret = 0;
@@ -37,7 +34,7 @@
  
  	dev_err(dev, "try to get sw efuse\n");
  
-@@ -1068,6 +1073,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
+@@ -1078,6 +1083,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
  
  	switch (instance->type) {
  	case PHY_TYPE_USB2:
@@ -58,7 +55,7 @@
  		ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr);
  		if (ret) {
  			dev_err(dev, "fail to get u2 intr efuse, %d\n", ret);
-@@ -1085,6 +1104,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
+@@ -1095,6 +1114,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
  		break;
  	case PHY_TYPE_USB3:
  	case PHY_TYPE_PCIE:
@@ -79,7 +76,7 @@
  		ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr);
  		if (ret) {
  			dev_err(dev, "fail to get u3 intr efuse, %d\n", ret);
-@@ -1119,6 +1152,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
+@@ -1129,6 +1162,20 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc
  		if (tphy->pdata->version != MTK_PHY_V4)
  			break;
  
@@ -100,7 +97,7 @@
  		ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1", &instance->efuse_intr_ln1);
  		if (ret) {
  			dev_err(dev, "fail to get u3 lane1 intr efuse, %d\n", ret);
-@@ -1170,6 +1217,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1180,6 +1227,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  
  	switch (instance->type) {
  	case PHY_TYPE_USB2:
@@ -111,7 +108,7 @@
  		tmp = readl(u2_banks->misc + U3P_MISC_REG1);
  		tmp |= MR1_EFUSE_AUTO_LOAD_DIS;
  		writel(tmp, u2_banks->misc + U3P_MISC_REG1);
-@@ -1182,6 +1233,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1192,6 +1243,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  
  		break;
  	case PHY_TYPE_USB3:
@@ -122,7 +119,7 @@
  		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
  		tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS;
  		writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV);
-@@ -1208,6 +1263,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1218,6 +1273,10 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  
  		break;
  	case PHY_TYPE_PCIE:
@@ -133,7 +130,7 @@
  		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
  		tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS;
  		writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV);
-@@ -1232,9 +1291,11 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
+@@ -1242,9 +1301,11 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
  			__func__, instance->efuse_tx_imp,
  			instance->efuse_rx_imp, instance->efuse_intr);
  
@@ -149,5 +146,5 @@
  
  		tmp = readl(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_RSV);
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2614-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
similarity index 77%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2614-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
index 36362f5..ef3b3a6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2614-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
@@ -1,20 +1,18 @@
-From 3295585b4e77f4a365bd1a4e17d8be6ee504584a Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Sat, 15 Oct 2022 17:38:54 +0800
-Subject: [PATCH 5/8] tphy: one setting of TTSSC-Freq-Dev for all IC cases
+From a977dbd79bc888d32fb974f328efa650722590c2 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:26 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2614-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch]
 
-try to use one setting of TTSSC-Freq-Dev to covery all IC cases
-
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/phy/mediatek/phy-mtk-tphy.c | 37 +++++++++++++++++++++++++++++
  1 file changed, 37 insertions(+)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index a5b17a1aed5c..49a2625c1fc1 100644
+index 149464f37..e7ed93799 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
-@@ -219,6 +219,14 @@
+@@ -221,6 +221,14 @@
  #define P3D_RG_RXDET_STB2_SET_P3	GENMASK(8, 0)
  #define P3D_RG_RXDET_STB2_SET_P3_VAL(x)	(0x1ff & (x))
  
@@ -29,7 +27,7 @@
  #define U3P_SPLLC_XTALCTL3		0x018
  #define XC3_RG_U3_XTAL_RX_PWD		BIT(9)
  #define XC3_RG_U3_FRC_XTAL_RX_PWD	BIT(8)
-@@ -373,6 +381,8 @@ struct mtk_phy_instance {
+@@ -378,6 +386,8 @@ struct mtk_phy_instance {
  	int eye_vrt;
  	int eye_term;
  	bool bc12_en;
@@ -38,7 +36,7 @@
  };
  
  struct mtk_tphy {
-@@ -514,6 +524,20 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
+@@ -520,6 +530,20 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
  	tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
  	writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
  
@@ -59,7 +57,7 @@
  	dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
  }
  
-@@ -942,6 +966,19 @@ static void phy_parse_property(struct mtk_tphy *tphy,
+@@ -952,6 +976,19 @@ static void phy_parse_property(struct mtk_tphy *tphy,
  {
  	struct device *dev = &instance->phy->dev;
  
@@ -80,5 +78,5 @@
  		return;
  
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
similarity index 89%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
index c20e930..fcd38ac 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
@@ -1,5 +1,15 @@
+From 50cefacc6c001eea1d9b1c78ba27304566f304f1 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:26 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch]
+
+---
+ drivers/phy/mediatek/phy-mtk-xsphy.c | 81 +++++++++++++++++++++++++++-
+ 1 file changed, 80 insertions(+), 1 deletion(-)
+
 diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
-index 8c51131..e77092c 100644
+index 8c5113194..e77092c3e 100644
 --- a/drivers/phy/mediatek/phy-mtk-xsphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
 @@ -12,10 +12,12 @@
@@ -140,3 +150,6 @@
  	}
  
  	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
similarity index 80%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
index 9d1ca10..f38ed0d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
@@ -1,21 +1,16 @@
-From 0df9413c8ff0df4ed69b6e1577d7cd5fd2d72e5e Mon Sep 17 00:00:00 2001
+From 9ef2a9d208fba86dfbc06d4f2f743562bd14c145 Mon Sep 17 00:00:00 2001
 From: Sam Shih <sam.shih@mediatek.com>
-Date: Tue, 25 Oct 2022 18:25:25 +0800
-Subject: [PATCH 1/3] xHCI: change compliance mode de-emphasis default as gen1
+Date: Fri, 2 Jun 2023 13:06:26 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch]
 
-Port0 is using Gen2 Phy for 10GHz, and Port0 is running
-on 5GHz actually. hence to change compliance mode de-
-emphasis default as Gen1.
-
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Signed-off-by: Sam Shih <sam.shih@mediatek.com>
 ---
  drivers/usb/host/xhci-mtk.c | 18 +++++++++++++++++-
  drivers/usb/host/xhci-mtk.h |  1 +
  2 files changed, 18 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
-index 5c0eb35cd007..77ddb8c05500 100644
+index 5c0eb35cd..77ddb8c05 100644
 --- a/drivers/usb/host/xhci-mtk.c
 +++ b/drivers/usb/host/xhci-mtk.c
 @@ -22,6 +22,11 @@
@@ -65,7 +60,7 @@
  	if (ret) {
  		dev_err(dev, "failed to parse uwk property\n");
 diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
-index 2f702342de66..8a884e7b481b 100644
+index 2f702342d..8a884e7b4 100644
 --- a/drivers/usb/host/xhci-mtk.h
 +++ b/drivers/usb/host/xhci-mtk.h
 @@ -156,6 +156,7 @@ struct xhci_hcd_mtk {
@@ -77,5 +72,5 @@
  
  static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9001-PATCH-1-2-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch
similarity index 86%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9001-PATCH-1-2-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch
index 07b87fc..d6974a5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9001-PATCH-1-2-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch
@@ -1,11 +1,9 @@
-From 083b79c977495cafc70c5d044db1f3f6c0587b1c Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Mon, 15 Aug 2022 12:40:22 +0800
-Subject: [PATCH 2/3] xHCI: MT79xx USB 2.0 USBIF compliance toolkit
+From f6aea6b89ce99b4f490fe1e1062b88042096703e Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:26 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch]
 
-MT79xx USB 2.0 USBIF compliance toolkit
-
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/usb/host/Kconfig    |  9 +++++++++
  drivers/usb/host/Makefile   | 10 ++++++++++
@@ -16,7 +14,7 @@
  6 files changed, 32 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
-index 79b2e79dddd0..12b1bf9aa043 100644
+index 79b2e79dd..12b1bf9aa 100644
 --- a/drivers/usb/host/Kconfig
 +++ b/drivers/usb/host/Kconfig
 @@ -69,6 +69,15 @@ config USB_XHCI_MTK
@@ -36,7 +34,7 @@
  	tristate "xHCI support for Marvell Armada 375/38x/37xx"
  	select USB_XHCI_PLATFORM
 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
-index b191361257cc..f064f836db2b 100644
+index b19136125..f064f836d 100644
 --- a/drivers/usb/host/Makefile
 +++ b/drivers/usb/host/Makefile
 @@ -21,6 +21,16 @@ endif
@@ -57,7 +55,7 @@
  
  xhci-plat-hcd-y := xhci-plat.o
 diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
-index 77ddb8c05500..7a200793169b 100644
+index 77ddb8c05..7a2007931 100644
 --- a/drivers/usb/host/xhci-mtk.c
 +++ b/drivers/usb/host/xhci-mtk.c
 @@ -18,10 +18,10 @@
@@ -90,7 +88,7 @@
  	pm_runtime_put_noidle(&dev->dev);
  	pm_runtime_disable(&dev->dev);
 diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
-index 8a884e7b481b..e815d7091acc 100644
+index 8a884e7b4..e815d7091 100644
 --- a/drivers/usb/host/xhci-mtk.h
 +++ b/drivers/usb/host/xhci-mtk.h
 @@ -157,6 +157,13 @@ struct xhci_hcd_mtk {
@@ -108,10 +106,10 @@
  
  static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)
 diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
-index 5ce16a259e61..b6f8383f7371 100644
+index b8915790a..dd1b520af 100644
 --- a/drivers/usb/host/xhci.c
 +++ b/drivers/usb/host/xhci.c
-@@ -713,7 +713,7 @@ EXPORT_SYMBOL_GPL(xhci_run);
+@@ -714,7 +714,7 @@ EXPORT_SYMBOL_GPL(xhci_run);
   * Disable device contexts, disable IRQs, and quiesce the HC.
   * Reset the HC, finish any completed transactions, and cleanup memory.
   */
@@ -121,10 +119,10 @@
  	u32 temp;
  	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
-index 0dc448630197..80b3124c43e2 100644
+index e696f1508..07f904167 100644
 --- a/drivers/usb/host/xhci.h
 +++ b/drivers/usb/host/xhci.h
-@@ -2070,6 +2070,7 @@ int xhci_halt(struct xhci_hcd *xhci);
+@@ -2073,6 +2073,7 @@ int xhci_halt(struct xhci_hcd *xhci);
  int xhci_start(struct xhci_hcd *xhci);
  int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us);
  int xhci_run(struct usb_hcd *hcd);
@@ -133,5 +131,5 @@
  void xhci_shutdown(struct usb_hcd *hcd);
  void xhci_init_driver(struct hc_driver *drv,
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9002-PATCH-1-1-usb-add-embedded-Host-feature-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2622-usb-add-embedded-Host-feature-support.patch
similarity index 77%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9002-PATCH-1-1-usb-add-embedded-Host-feature-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2622-usb-add-embedded-Host-feature-support.patch
index c4970eb..7776441 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9002-PATCH-1-1-usb-add-embedded-Host-feature-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2622-usb-add-embedded-Host-feature-support.patch
@@ -1,18 +1,9 @@
-From be6839b4144867c7ea6ffbedb6c6a2a42976e16d Mon Sep 17 00:00:00 2001
-From: Zhanyong Wang <zhanyong.wang@mediatek.com>
-Date: Thu, 17 Jun 2021 16:09:04 +0800
-Subject: [PATCH 3/3] usb: add embedded Host feature support
+From 32950d08c99f51e88a2db8dd30c5076a4947de24 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:27 +0800
+Subject: [PATCH] 
+ [high-speed-io][999-2622-usb-add-embedded-Host-feature-support.patch]
 
-add EH(Embedded Host) feature for PET authentication
-1. need CONFIG_USB_OTG_WHITELIST enable
-   CONFIG_USB_OTG_WHITELIST=y
-
-2. host device tree node need include "tpl-support" keyword
-   &xhci {
-	   tpl-support;
-   }
-
-Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
  drivers/usb/core/hub.c           |  9 +++++---
  drivers/usb/core/otg_whitelist.h | 39 ++++++++++++++++++++++++++++++++
@@ -20,10 +11,10 @@
  3 files changed, 47 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 4cf0dc7f330d..f2f330606d0c 100644
+index f787e9771..7687711f1 100644
 --- a/drivers/usb/core/hub.c
 +++ b/drivers/usb/core/hub.c
-@@ -2422,6 +2422,8 @@ static int usb_enumerate_device(struct usb_device *udev)
+@@ -2424,6 +2424,8 @@ static int usb_enumerate_device(struct usb_device *udev)
  			if (err < 0)
  				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
  		}
@@ -32,7 +23,7 @@
  		return -ENOTSUPP;
  	}
  
-@@ -4779,9 +4781,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+@@ -4781,9 +4783,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
  				goto fail;
  			}
  			if (r) {
@@ -47,7 +38,7 @@
  				continue;
  			}
 diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
-index 2ae90158ded7..a8dd221334c1 100644
+index 2ae90158d..a8dd22133 100644
 --- a/drivers/usb/core/otg_whitelist.h
 +++ b/drivers/usb/core/otg_whitelist.h
 @@ -39,9 +39,44 @@ static struct usb_device_id whitelist_table[] = {
@@ -107,10 +98,10 @@
  	}
  
 diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
-index d4345657945d..2a4b73a658f9 100644
+index 7a2007931..19b54c343 100644
 --- a/drivers/usb/host/xhci-mtk.c
 +++ b/drivers/usb/host/xhci-mtk.c
-@@ -571,6 +571,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)
+@@ -575,6 +575,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)
  		goto disable_device_wakeup;
  	}
  
@@ -120,5 +111,5 @@
  	if (ret)
  		goto put_usb3_hcd;
 -- 
-2.18.0
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/744-en8811h-2p5gphy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2704-en8811h-2p5gphy-support.patch
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/744-en8811h-2p5gphy-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2704-en8811h-2p5gphy-support.patch
index 5a3e423..5e3c619 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/744-en8811h-2p5gphy-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2704-en8811h-2p5gphy-support.patch
@@ -1,10 +1,25 @@
+From b5aa08e6dd4e06ffd3fb4de2ffc6af1e3da0bce4 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:00 +0800
+Subject: [PATCH] 
+ [backport-networking-drivers][999-1703-en8811h-2p5gphy-support.patch]
+
+---
+ drivers/net/phy/Kconfig       |   5 +
+ drivers/net/phy/Makefile      |   1 +
+ drivers/net/phy/air_en8811h.c | 702 ++++++++++++++++++++++++++++++++++
+ drivers/net/phy/air_en8811h.h | 151 ++++++++
+ 4 files changed, 859 insertions(+)
+ create mode 100644 drivers/net/phy/air_en8811h.c
+ create mode 100644 drivers/net/phy/air_en8811h.h
+
 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 207046b..21a4497 100644
+index 170dd00cd..5eeccfee2 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -350,6 +350,11 @@ config AIROHA_EN8801SC_PHY
-         ---help---
-           Currently supports the Airoha EN8801S PHY for MT7981 SoC.
+@@ -345,6 +345,11 @@ config SFP
+ 	depends on HWMON || HWMON=n
+ 	select MDIO_I2C
  
 +config AIROHA_EN8811H_PHY
 +	tristate "Drivers for Airoha EN8811H 2.5G Gigabit PHY"
@@ -15,10 +30,10 @@
  	tristate "Analog Devices Industrial Ethernet PHYs"
  	help
 diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index 1b13c02..744b249 100644
+index 2368c1d19..8ea612a85 100644
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -71,6 +71,7 @@ ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
+@@ -67,6 +67,7 @@ aquantia-objs			+= aquantia_main.o
  ifdef CONFIG_HWMON
  aquantia-objs			+= aquantia_hwmon.o
  endif
@@ -28,7 +43,7 @@
  obj-$(CONFIG_AT803X_PHY)	+= at803x.o
 diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c
 new file mode 100644
-index 0000000..cf564fc
+index 000000000..cf564fc04
 --- /dev/null
 +++ b/drivers/net/phy/air_en8811h.c
 @@ -0,0 +1,702 @@
@@ -736,7 +751,7 @@
 +module_exit(en8811h_phy_driver_unregister);
 diff --git a/drivers/net/phy/air_en8811h.h b/drivers/net/phy/air_en8811h.h
 new file mode 100644
-index 0000000..1c91627
+index 000000000..1c9162795
 --- /dev/null
 +++ b/drivers/net/phy/air_en8811h.h
 @@ -0,0 +1,151 @@
@@ -891,3 +906,6 @@
 +} AIR_LED_MODE_T;
 +
 +#endif /* End of __EN8811H_MD32_H */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0100-hwnat_Kconfig_Makefile.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2705-hwnat_Kconfig_Makefile.patch
old mode 100755
new mode 100644
similarity index 61%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0100-hwnat_Kconfig_Makefile.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2705-hwnat_Kconfig_Makefile.patch
index e0ac7ab..fbb8410
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0100-hwnat_Kconfig_Makefile.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2705-hwnat_Kconfig_Makefile.patch
@@ -1,6 +1,18 @@
---- a/net/Kconfig	2020-04-29 17:25:49.750444000 +0800
-+++ b/net/Kconfig	2020-04-29 17:42:40.950424000 +0800
-@@ -451,6 +451,18 @@
+From bc06d56dc89af9d13d3b993dae0de46e76dfc3a7 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:28 +0800
+Subject: [PATCH] [networking][999-2705-hwnat_Kconfig_Makefile.patch]
+
+---
+ net/Kconfig  | 12 ++++++++++++
+ net/Makefile |  3 +++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/net/Kconfig b/net/Kconfig
+index 46d9b3827..123e4bc28 100644
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -460,6 +460,18 @@ config FAILOVER
  	  migration of VMs with direct attached VFs by failing over to the
  	  paravirtual datapath when the VF is unplugged.
  
@@ -19,9 +31,11 @@
  endif   # if NET
  
  # Used by archs to tell that they support BPF JIT compiler plus which flavour.
---- a/net/Makefile	2020-04-23 16:36:46.000000000 +0800
-+++ b/net/Makefile	2020-04-29 17:42:58.106487000 +0800
-@@ -62,6 +62,9 @@
+diff --git a/net/Makefile b/net/Makefile
+index 9603e98f0..673f0a664 100644
+--- a/net/Makefile
++++ b/net/Makefile
+@@ -62,6 +62,9 @@ endif
  obj-$(CONFIG_6LOWPAN)		+= 6lowpan/
  obj-$(CONFIG_IEEE802154)	+= ieee802154/
  obj-$(CONFIG_MAC802154)		+= mac802154/
@@ -31,3 +45,6 @@
  
  ifeq ($(CONFIG_NET),y)
  obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2706-crypto-add-eip197-inside-secure-support.patch
similarity index 82%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2706-crypto-add-eip197-inside-secure-support.patch
index 8b9ccce..a144c36 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2706-crypto-add-eip197-inside-secure-support.patch
@@ -1,6 +1,19 @@
+From 7baac266ec5e64236ff94447286a9cc74815d259 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:28 +0800
+Subject: [PATCH] 
+ [networking][999-2706-crypto-add-eip197-inside-secure-support.patch]
+
+---
+ drivers/crypto/inside-secure/safexcel.c | 69 ++++++++++++++++++++++---
+ drivers/crypto/inside-secure/safexcel.h | 15 ++++++
+ 2 files changed, 78 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
+index 647c5a0c1..6f4fc15b7 100644
 --- a/drivers/crypto/inside-secure/safexcel.c
 +++ b/drivers/crypto/inside-secure/safexcel.c
-@@ -304,6 +304,11 @@
+@@ -304,6 +304,11 @@ static void eip197_init_firmware(struct safexcel_crypto_priv *priv)
  		/* Enable access to all IFPP program memories */
  		writel(EIP197_PE_ICE_RAM_CTRL_FPP_PROG_EN,
  		       EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));
@@ -12,7 +25,7 @@
  	}
  
  }
-@@ -403,13 +408,13 @@
+@@ -403,13 +408,13 @@ static int eip197_load_firmwares(struct safexcel_crypto_priv *priv)
  	const struct firmware *fw[FW_NB];
  	char fw_path[37], *dir = NULL;
  	int i, j, ret = 0, pe;
@@ -28,7 +41,7 @@
  	else
  		return -ENODEV;
  
-@@ -442,6 +447,9 @@
+@@ -442,6 +447,9 @@ retry_fw:
  
  	ipuesz = eip197_write_firmware(priv, fw[FW_IPUE]);
  
@@ -38,7 +51,7 @@
  	if (eip197_start_firmware(priv, ipuesz, ifppsz, minifw)) {
  		dev_dbg(priv->dev, "Firmware loaded successfully\n");
  		return 0;
-@@ -592,6 +600,11 @@
+@@ -592,6 +600,11 @@ static int safexcel_hw_init(struct safexcel_crypto_priv *priv)
  	 */
  	if (priv->flags & SAFEXCEL_HW_EIP197) {
  		val = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
@@ -50,7 +63,7 @@
  		val |= EIP197_MST_CTRL_TX_MAX_CMD(5);
  		writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
  	}
-@@ -792,6 +805,12 @@
+@@ -792,6 +805,12 @@ static int safexcel_hw_init(struct safexcel_crypto_priv *priv)
  			return ret;
  	}
  
@@ -63,7 +76,7 @@
  	return safexcel_hw_setup_cdesc_rings(priv) ?:
  	       safexcel_hw_setup_rdesc_rings(priv) ?:
  	       0;
-@@ -1498,6 +1517,9 @@
+@@ -1498,6 +1517,9 @@ static int safexcel_probe_generic(void *pdev,
  	hwopt = readl(EIP197_GLOBAL(priv) + EIP197_OPTIONS);
  	hiaopt = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_OPTIONS);
  
@@ -73,7 +86,7 @@
  	if (priv->flags & SAFEXCEL_HW_EIP197) {
  		/* EIP197 */
  		peopt = readl(EIP197_PE(priv) + EIP197_PE_OPTIONS(0));
-@@ -1516,8 +1538,37 @@
+@@ -1516,8 +1538,37 @@ static int safexcel_probe_generic(void *pdev,
  					    EIP197_N_RINGS_MASK;
  		if (hiaopt & EIP197_HIA_OPT_HAS_PE_ARB)
  			priv->flags |= EIP197_PE_ARB;
@@ -112,7 +125,7 @@
  		/* If not a full TRC, then assume simple TRC */
  		if (!(hwopt & EIP197_OPT_HAS_TRC))
  			priv->flags |= EIP197_SIMPLE_TRC;
-@@ -1555,13 +1606,14 @@
+@@ -1555,13 +1606,14 @@ static int safexcel_probe_generic(void *pdev,
  				    EIP197_PE_EIP96_OPTIONS(0));
  
  	/* Print single info line describing what we just detected */
@@ -129,7 +142,7 @@
  
  	safexcel_configure(priv);
  
-@@ -1690,6 +1742,7 @@
+@@ -1690,6 +1742,7 @@ static int safexcel_probe(struct platform_device *pdev)
  {
  	struct device *dev = &pdev->dev;
  	struct safexcel_crypto_priv *priv;
@@ -137,7 +150,7 @@
  	int ret;
  
  	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-@@ -1701,7 +1754,11 @@
+@@ -1701,7 +1754,11 @@ static int safexcel_probe(struct platform_device *pdev)
  
  	platform_set_drvdata(pdev, priv);
  
@@ -150,6 +163,8 @@
  	if (IS_ERR(priv->base)) {
  		dev_err(dev, "failed to get resource\n");
  		return PTR_ERR(priv->base);
+diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h
+index c031c197e..e9909c336 100644
 --- a/drivers/crypto/inside-secure/safexcel.h
 +++ b/drivers/crypto/inside-secure/safexcel.h
 @@ -22,6 +22,7 @@
@@ -202,7 +217,7 @@
  /* EIP197_STRC_CONFIG */
  #define EIP197_STRC_CONFIG_INIT			BIT(31)
  #define EIP197_STRC_CONFIG_LARGE_REC(s)		(s<<8)
-@@ -777,6 +788,7 @@
+@@ -777,6 +788,7 @@ enum safexcel_flags {
  	EIP197_PE_ARB		= BIT(2),
  	EIP197_ICE		= BIT(3),
  	EIP197_SIMPLE_TRC	= BIT(4),
@@ -210,7 +225,7 @@
  };
  
  struct safexcel_hwconfig {
-@@ -784,7 +796,10 @@
+@@ -784,7 +796,10 @@ struct safexcel_hwconfig {
  	int hwver;
  	int hiaver;
  	int ppver;
@@ -221,3 +236,6 @@
  	int hwdataw;
  	int hwcfsize;
  	int hwrfsize;
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1001-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2707-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch
similarity index 66%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1001-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2707-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch
index 72719c8..879e79d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1001-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2707-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch
@@ -1,5 +1,15 @@
+From 5583834362f5a9050e701e324f6a9b4d7bf5fcdf Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:29 +0800
+Subject: [PATCH] 
+ [networking][999-2707-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch]
+
+---
+ net/core/skbuff.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
 diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 5ba1c72f..f4239459 100644
+index 409f33e16..d91b2dfe2 100644
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
 @@ -69,6 +69,7 @@
@@ -20,3 +30,6 @@
  	/*
  	 * if shinfo is shared we must drop the old head gracefully, but if it
  	 * is not we can just drop the old head and let the existing refcount
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2709-fix-race-inside-napi-enable.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2709-fix-race-inside-napi-enable.patch
new file mode 100644
index 0000000..0d90686
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2709-fix-race-inside-napi-enable.patch
@@ -0,0 +1,39 @@
+From f57826291fc2ff833c01b39c01fa5b74b69485da Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:29 +0800
+Subject: [PATCH] [networking][999-2709-fix-race-inside-napi-enable.patch]
+
+---
+ net/core/dev.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 81892cd83..503af0034 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6413,12 +6413,16 @@ EXPORT_SYMBOL(napi_disable);
+  */
+ void napi_enable(struct napi_struct *n)
+ {
+-	BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
+-	smp_mb__before_atomic();
+-	clear_bit(NAPI_STATE_SCHED, &n->state);
+-	clear_bit(NAPI_STATE_NPSVC, &n->state);
+-	if (n->dev->threaded && n->thread)
+-		set_bit(NAPI_STATE_THREADED, &n->state);
++	unsigned long val, new;
++
++	do {
++		val = READ_ONCE(n->state);
++		BUG_ON(!test_bit(NAPI_STATE_SCHED, &val));
++
++		new = val & ~(NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC);
++		if (n->dev->threaded && n->thread)
++			new |= NAPIF_STATE_THREADED;
++	} while (cmpxchg(&n->state, val, new) != val);
+ }
+ EXPORT_SYMBOL(napi_enable);
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2710-net-make-napi-disable-symmetric-with-enable.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2710-net-make-napi-disable-symmetric-with-enable.patch
new file mode 100644
index 0000000..0de5a63
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2710-net-make-napi-disable-symmetric-with-enable.patch
@@ -0,0 +1,48 @@
+From 8e758bb3fc5eee316843eeaad1601ee44ce1c899 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:30 +0800
+Subject: [PATCH] 
+ [networking][999-2710-net-make-napi-disable-symmetric-with-enable.patch]
+
+---
+ net/core/dev.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 503af0034..cccd7b407 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6389,18 +6389,25 @@ EXPORT_SYMBOL(netif_napi_add);
+ 
+ void napi_disable(struct napi_struct *n)
+ {
++	unsigned long val, new;
++
+ 	might_sleep();
+ 	set_bit(NAPI_STATE_DISABLE, &n->state);
+ 
+-	while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
+-		msleep(1);
+-	while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state))
+-		msleep(1);
++	do {
++		val = READ_ONCE(n->state);
++		if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
++			usleep_range(20, 200);
++			continue;
++		}
++
++		new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC;
++		new &= ~(NAPIF_STATE_THREADED);
++	} while (cmpxchg(&n->state, val, new) != val);
+ 
+ 	hrtimer_cancel(&n->timer);
+ 
+ 	clear_bit(NAPI_STATE_DISABLE, &n->state);
+-	clear_bit(NAPI_STATE_THREADED, &n->state);
+ }
+ EXPORT_SYMBOL(napi_disable);
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2711-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2711-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch
new file mode 100644
index 0000000..ef18a49
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2711-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch
@@ -0,0 +1,38 @@
+From a3eac970a1a3e2fc8cdc98acd2594e0578725ad6 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:30 +0800
+Subject: [PATCH] 
+ [networking][999-2711-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch]
+
+---
+ net/core/dev.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index cccd7b407..794c768e3 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6394,7 +6394,7 @@ void napi_disable(struct napi_struct *n)
+ 	might_sleep();
+ 	set_bit(NAPI_STATE_DISABLE, &n->state);
+ 
+-	do {
++	for ( ; ; ) {
+ 		val = READ_ONCE(n->state);
+ 		if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
+ 			usleep_range(20, 200);
+@@ -6403,7 +6403,10 @@ void napi_disable(struct napi_struct *n)
+ 
+ 		new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC;
+ 		new &= ~(NAPIF_STATE_THREADED);
+-	} while (cmpxchg(&n->state, val, new) != val);
++
++		if (cmpxchg(&n->state, val, new) == val)
++			break;
++	}
+ 
+ 	hrtimer_cancel(&n->timer);
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/730-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2712-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch
similarity index 68%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/730-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2712-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch
index 6b10584..a76a784 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/730-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2712-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch
@@ -1,6 +1,18 @@
---- linux-5.4.77.orig/net/dsa/tag_mtk.c
-+++ linux-5.4.77/net/dsa/tag_mtk.c
-@@ -73,22 +73,28 @@ static struct sk_buff *mtk_tag_rcv(struc
+From 0f2e84b06686745694f276c4aae6cf9d132a56af Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:30 +0800
+Subject: [PATCH] 
+ [networking][999-2712-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch]
+
+---
+ net/dsa/tag_mtk.c | 32 +++++++++++++++++++-------------
+ 1 file changed, 19 insertions(+), 13 deletions(-)
+
+diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
+index edc505e07..c386fdc90 100644
+--- a/net/dsa/tag_mtk.c
++++ b/net/dsa/tag_mtk.c
+@@ -80,22 +80,28 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
  	bool is_multicast_skb = is_multicast_ether_addr(dest) &&
  				!is_broadcast_ether_addr(dest);
  
@@ -42,3 +54,6 @@
  
  	/* Get source port information */
  	port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/738-mt7531-gsw-internal_phy_calibration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2713-mt7531-gsw-internal_phy_calibration.patch
old mode 100755
new mode 100644
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/738-mt7531-gsw-internal_phy_calibration.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2713-mt7531-gsw-internal_phy_calibration.patch
index 361eca6..e0759b2
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/738-mt7531-gsw-internal_phy_calibration.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2713-mt7531-gsw-internal_phy_calibration.patch
@@ -1,5 +1,21 @@
-Index: drivers/net/phy/mtk/mt753x/Makefile
-===================================================================
+From e17d8763f1279f43edf51a8ceb8b4f78d67eaefa Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:30 +0800
+Subject: [PATCH] 
+ [networking][999-2713-mt7531-gsw-internal_phy_calibration.patch]
+
+---
+ drivers/net/phy/mtk/mt753x/Makefile     |    2 +-
+ drivers/net/phy/mtk/mt753x/mt7531.c     |   21 +
+ drivers/net/phy/mtk/mt753x/mt753x.h     |    2 +
+ drivers/net/phy/mtk/mt753x/mt753x_phy.c | 1069 +++++++++++++++++++++++
+ drivers/net/phy/mtk/mt753x/mt753x_phy.h |  145 +++
+ 5 files changed, 1238 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/phy/mtk/mt753x/mt753x_phy.c
+ create mode 100644 drivers/net/phy/mtk/mt753x/mt753x_phy.h
+
+diff --git a/drivers/net/phy/mtk/mt753x/Makefile b/drivers/net/phy/mtk/mt753x/Makefile
+index e304fcb41..b5a63fe91 100644
 --- a/drivers/net/phy/mtk/mt753x/Makefile
 +++ b/drivers/net/phy/mtk/mt753x/Makefile
 @@ -7,5 +7,5 @@ obj-$(CONFIG_MT753X_GSW)	+= mt753x.o
@@ -9,11 +25,11 @@
 -					mt753x_common.o mt753x_vlan.o mt753x_nl.o
 +					mt753x_common.o mt753x_vlan.o mt753x_nl.o mt753x_phy.o
  
-Index: drivers/net/phy/mtk/mt753x/mt7531.c
-===================================================================
+diff --git a/drivers/net/phy/mtk/mt753x/mt7531.c b/drivers/net/phy/mtk/mt753x/mt7531.c
+index b27c679a5..512a89a94 100755
 --- a/drivers/net/phy/mtk/mt753x/mt7531.c
 +++ b/drivers/net/phy/mtk/mt753x/mt7531.c
-@@ -658,6 +658,27 @@ static void mt7531_core_pll_setup(struct
+@@ -662,6 +662,27 @@ static void mt7531_core_pll_setup(struct gsw_mt753x *gsw)
  
  static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw)
  {
@@ -41,11 +57,11 @@
  	return 0;
  }
  
-Index: drivers/net/phy/mtk/mt753x/mt753x.h
-===================================================================
+diff --git a/drivers/net/phy/mtk/mt753x/mt753x.h b/drivers/net/phy/mtk/mt753x/mt753x.h
+index 344d2b0c6..252ce350f 100644
 --- a/drivers/net/phy/mtk/mt753x/mt753x.h
 +++ b/drivers/net/phy/mtk/mt753x/mt753x.h
-@@ -140,6 +140,8 @@ void mt753x_irq_enable(struct gsw_mt753x
+@@ -146,6 +146,8 @@ void mt753x_irq_enable(struct gsw_mt753x *gsw);
  int mt753x_phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr);
  int extphy_init(struct gsw_mt753x *gsw, int addr);
  
@@ -54,9 +70,9 @@
  /* MDIO Indirect Access Registers */
  #define MII_MMD_ACC_CTL_REG		0x0d
  #define MMD_CMD_S			14
-Index: drivers/net/phy/mtk/mt753x/mt753x_phy.c
-===================================================================
+diff --git a/drivers/net/phy/mtk/mt753x/mt753x_phy.c b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
 new file mode 100644
+index 000000000..0c6f9c930
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
 @@ -0,0 +1,1069 @@
@@ -1129,9 +1145,9 @@
 +
 +	return ret;
 +}
-Index: drivers/net/phy/mtk/mt753x/mt753x_phy.h
-===================================================================
+diff --git a/drivers/net/phy/mtk/mt753x/mt753x_phy.h b/drivers/net/phy/mtk/mt753x/mt753x_phy.h
 new file mode 100644
+index 000000000..1b9e2ea80
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.h
 @@ -0,0 +1,145 @@
@@ -1280,3 +1296,6 @@
 +#define DA_TX_I2MPB_D_GBE		BITS(8, 13)
 +
 +#endif /* _MT753X_REGS_H_ */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/739-mt7531-gsw-port5_external_phy_init.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2714-mt7531-gsw-port5_external_phy_init.patch
old mode 100755
new mode 100644
similarity index 87%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/739-mt7531-gsw-port5_external_phy_init.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2714-mt7531-gsw-port5_external_phy_init.patch
index 0d88c60..237c68e
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/739-mt7531-gsw-port5_external_phy_init.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2714-mt7531-gsw-port5_external_phy_init.patch
@@ -1,9 +1,9 @@
-From 9206472ba03032aea120604e8637b52408ca4b3a Mon Sep 17 00:00:00 2001
-From: Landen Chao <landen.chao@mediatek.com>
-Date: Fri, 29 May 2020 15:12:35 +0800
-Subject: [PATCH 2/2] 740_patch
+From 13b169a35dfff523263d20d0d97e46401f6c692f Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:31 +0800
+Subject: [PATCH] 
+ [networking][999-2714-mt7531-gsw-port5_external_phy_init.patch]
 
-Change-Id: I7e0164751702f573d5185c4290ff78688f42f603
 ---
  drivers/net/phy/mtk/mt753x/Makefile        |  3 +-
  drivers/net/phy/mtk/mt753x/mt7531.c        |  3 +
@@ -15,7 +15,7 @@
  create mode 100644 drivers/net/phy/mtk/mt753x/mt753x_extphy.h
 
 diff --git a/drivers/net/phy/mtk/mt753x/Makefile b/drivers/net/phy/mtk/mt753x/Makefile
-index 384b0ff7..694ffa83 100644
+index b5a63fe91..16e977528 100644
 --- a/drivers/net/phy/mtk/mt753x/Makefile
 +++ b/drivers/net/phy/mtk/mt753x/Makefile
 @@ -7,5 +7,6 @@ obj-$(CONFIG_MT753X_GSW)	+= mt753x.o
@@ -27,10 +27,10 @@
 +					mt753x_extphy.o
  
 diff --git a/drivers/net/phy/mtk/mt753x/mt7531.c b/drivers/net/phy/mtk/mt753x/mt7531.c
-index 04729835..4a2943b1 100644
+index 512a89a94..3e2187d21 100755
 --- a/drivers/net/phy/mtk/mt753x/mt7531.c
 +++ b/drivers/net/phy/mtk/mt753x/mt7531.c
-@@ -265,6 +265,9 @@ static int mt7531_set_port_sgmii_force_mode(struct gsw_mt753x *gsw, u32 port,
+@@ -264,6 +264,9 @@ static int mt7531_set_port_sgmii_force_mode(struct gsw_mt753x *gsw, u32 port,
  		return -EINVAL;
  	}
  
@@ -41,11 +41,11 @@
  
  	switch (port_cfg->speed) {
 diff --git a/drivers/net/phy/mtk/mt753x/mt753x.h b/drivers/net/phy/mtk/mt753x/mt753x.h
-index 5053a7d7..a3f343cd 100644
+index 252ce350f..c23fd9e5f 100644
 --- a/drivers/net/phy/mtk/mt753x/mt753x.h
 +++ b/drivers/net/phy/mtk/mt753x/mt753x.h
-@@ -154,6 +154,7 @@ void mt753x_irq_worker(struct work_struct *work);
- void mt753x_irq_enable(struct gsw_mt753x *gsw);
+@@ -147,6 +147,7 @@ int mt753x_phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr);
+ int extphy_init(struct gsw_mt753x *gsw, int addr);
  
  int mt753x_phy_calibration(struct gsw_mt753x *gsw, u8 phyaddr);
 +int extphy_init(struct gsw_mt753x *gsw, int addr);
@@ -54,7 +54,7 @@
  #define MII_MMD_ACC_CTL_REG		0x0d
 diff --git a/drivers/net/phy/mtk/mt753x/mt753x_extphy.c b/drivers/net/phy/mtk/mt753x/mt753x_extphy.c
 new file mode 100644
-index 00000000..f58e8a62
+index 000000000..f58e8a62d
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_extphy.c
 @@ -0,0 +1,69 @@
@@ -129,7 +129,7 @@
 +}
 diff --git a/drivers/net/phy/mtk/mt753x/mt753x_extphy.h b/drivers/net/phy/mtk/mt753x/mt753x_extphy.h
 new file mode 100644
-index 00000000..2b72c8a9
+index 000000000..2b72c8a9d
 --- /dev/null
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_extphy.h
 @@ -0,0 +1,18 @@
@@ -152,5 +152,5 @@
 +};
 +#endif
 -- 
-2.17.1
+2.34.1
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2715-add-gpy211-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2715-add-gpy211-phy-support.patch
new file mode 100644
index 0000000..7613c86
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2715-add-gpy211-phy-support.patch
@@ -0,0 +1,41 @@
+From e18ad3270a1bdd776f5d7b13c4756efbd890825b Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:31 +0800
+Subject: [PATCH] [networking][999-2715-add-gpy211-phy-support.patch]
+
+---
+ drivers/net/phy/Kconfig  | 5 +++++
+ drivers/net/phy/Makefile | 1 +
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index ec5c66d0a..3a3c12566 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -473,6 +473,11 @@ config FIXED_PHY
+ 
+ 	  Currently tested with mpc866ads and mpc8349e-mitx.
+ 
++config GPY211_PHY
++	tristate "GPY211 PHY"
++	---help---
++	  Supports the Intel GPY211 PHY with rate adaption.
++
+ config ICPLUS_PHY
+ 	tristate "ICPlus PHYs"
+ 	---help---
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index f4feb0e3d..1d368d1d5 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -88,6 +88,7 @@ obj-$(CONFIG_DP83TC811_PHY)	+= dp83tc811.o
+ obj-$(CONFIG_DP83848_PHY)	+= dp83848.o
+ obj-$(CONFIG_DP83867_PHY)	+= dp83867.o
+ obj-$(CONFIG_FIXED_PHY)		+= fixed_phy.o
++obj-$(CONFIG_GPY211_PHY)	+= gpy211.o
+ obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
+ obj-$(CONFIG_INTEL_XWAY_PHY)	+= intel-xway.o
+ obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2716-en8801sc-gphy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2716-en8801sc-gphy-support.patch
new file mode 100644
index 0000000..47168b9
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2716-en8801sc-gphy-support.patch
@@ -0,0 +1,41 @@
+From 43abbf9e88d9cf44e123a17d6d46db06fbb51da7 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:31 +0800
+Subject: [PATCH] [networking][999-2716-en8801sc-gphy-support.patch]
+
+---
+ drivers/net/phy/Kconfig  | 5 +++++
+ drivers/net/phy/Makefile | 1 +
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 3a3c12566..87eaaad76 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -345,6 +345,11 @@ config SFP
+ 	depends on HWMON || HWMON=n
+ 	select MDIO_I2C
+ 
++config AIROHA_EN8801SC_PHY
++	tristate "Drivers for Airoha EN8801S Gigabit PHYs for MediaTek SoC."
++	---help---
++	  Currently supports the Airoha EN8801S PHY for MediaTek SoC.
++
+ config AIROHA_EN8811H_PHY
+ 	tristate "Drivers for Airoha EN8811H 2.5G Gigabit PHY"
+ 	---help---
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 1d368d1d5..801550726 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -68,6 +68,7 @@ aquantia-objs			+= aquantia_main.o
+ ifdef CONFIG_HWMON
+ aquantia-objs			+= aquantia_hwmon.o
+ endif
++obj-$(CONFIG_AIROHA_EN8801SC_PHY)	+= en8801sc.o
+ obj-$(CONFIG_AIROHA_EN8811H_PHY)	+= air_en8811h.o
+ obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
+ obj-$(CONFIG_AX88796B_PHY)	+= ax88796b.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2717-add-mediatek-2p5ge-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2717-add-mediatek-2p5ge-phy-support.patch
new file mode 100644
index 0000000..b750c57
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2717-add-mediatek-2p5ge-phy-support.patch
@@ -0,0 +1,41 @@
+From d3e70b511ec583b7cced3ffd3c34700084c9149d Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:31 +0800
+Subject: [PATCH] [networking][999-2717-add-mediatek-2p5ge-phy-support.patch]
+
+---
+ drivers/net/phy/Kconfig  | 5 +++++
+ drivers/net/phy/Makefile | 1 +
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 87eaaad76..45aaf7203 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -539,6 +539,11 @@ config MEDIATEK_GE_SOC_PHY
+ 	  present in the SoCs efuse and will dynamically calibrate VCM
+ 	  (common-mode voltage) during startup.
+ 
++config MEDIATEK_2P5GE_PHY
++	tristate "MediaTek 2.5Gb Ethernet PHYs"
++	---help---
++	  Supports MediaTek internal 2.5Gb Ethernet PHYs.
++
+ config MICREL_PHY
+ 	tristate "Micrel PHYs"
+ 	---help---
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 801550726..998de790e 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -98,6 +98,7 @@ obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
+ obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)	+= mediatek-ge-soc.o
++obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
+ obj-$(CONFIG_MESON_GXL_PHY)	+= meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY)	+= micrel.o
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2719-net-phy-aquantia-add-firmware-download.patch
similarity index 96%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2719-net-phy-aquantia-add-firmware-download.patch
index 0e38dad..c128bbe 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2719-net-phy-aquantia-add-firmware-download.patch
@@ -1,5 +1,20 @@
+From 2fd17c806f5ad23f9958c358cdc26f618f05d5df Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:32 +0800
+Subject: [PATCH] 
+ [networking][999-2719-net-phy-aquantia-add-firmware-download.patch]
+
+---
+ drivers/net/phy/Kconfig             |   33 +-
+ drivers/net/phy/Makefile            |    3 +
+ drivers/net/phy/aquantia.h          |   64 ++
+ drivers/net/phy/aquantia_firmware.c | 1090 +++++++++++++++++++++++++++
+ drivers/net/phy/aquantia_main.c     |   92 ++-
+ 5 files changed, 1241 insertions(+), 41 deletions(-)
+ create mode 100644 drivers/net/phy/aquantia_firmware.c
+
 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 7b49c94..5a79af2 100644
+index c0e09c99d..d467834eb 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
 @@ -372,7 +372,38 @@ config AMD_PHY
@@ -43,10 +58,10 @@
  config AX88796B_PHY
  	tristate "Asix PHYs"
 diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index 043a697..4f67110 100644
+index 8b57d6105..e9653de36 100644
 --- a/drivers/net/phy/Makefile
 +++ b/drivers/net/phy/Makefile
-@@ -67,5 +67,8 @@ aquantia-objs			+= aquantia_main.o
+@@ -68,6 +68,9 @@ aquantia-objs			+= aquantia_main.o
  ifdef CONFIG_HWMON
  aquantia-objs			+= aquantia_hwmon.o
  endif
@@ -54,9 +69,10 @@
 +aquantia-objs			+= aquantia_firmware.o
 +endif
  obj-$(CONFIG_AIROHA_EN8801SC_PHY)	+= en8801sc.o
+ obj-$(CONFIG_AIROHA_EN8811H_PHY)	+= air_en8811h.o
  obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
 diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
-index 5a16caa..ab1c241 100644
+index 5a16caab7..ab1c241d3 100644
 --- a/drivers/net/phy/aquantia.h
 +++ b/drivers/net/phy/aquantia.h
 @@ -9,8 +9,72 @@
@@ -134,10 +150,10 @@
 +#endif
 diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
 new file mode 100644
-index 0000000..622557c
+index 000000000..d2828aad4
 --- /dev/null
 +++ b/drivers/net/phy/aquantia_firmware.c
-@@ -0,0 +1,1090 @@
+@@ -0,0 +1,1091 @@
 +// SPDX-License-Identifier: GPL-2.0
 +/* FW download driver for Aquantia PHY
 + */
@@ -1196,7 +1212,8 @@
 +						  "aqr_firmware_gandload_thread");
 +		if (IS_ERR(gangload_kthread)) {
 +			dev_err(dev,
-+				"failed to create aqr_firmware_gandload_thread\n");
++				"failed to create aqr_firmware_gandload_thread(%ld)\n",
++				 PTR_ERR(gangload_kthread));
 +			return PTR_ERR(gangload_kthread);
 +		}
 +		wake_up_process(gangload_kthread);
@@ -1229,7 +1246,7 @@
 +	return ret;
 +}
 diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
-index a8c828b..d98757f 100644
+index e7495c9a7..36f1aac4f 100644
 --- a/drivers/net/phy/aquantia_main.c
 +++ b/drivers/net/phy/aquantia_main.c
 @@ -8,10 +8,12 @@
@@ -1245,7 +1262,7 @@
  
  #include "aquantia.h"
  
-@@ -39,7 +40,6 @@
+@@ -39,7 +41,6 @@
  #define MDIO_AN_VEND_PROV_2500BASET_FULL	BIT(10)
  #define MDIO_AN_VEND_PROV_DOWNSHIFT_EN		BIT(4)
  #define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK	GENMASK(3, 0)
@@ -1253,7 +1270,7 @@
  
  #define MDIO_AN_TX_VEND_STATUS1			0xc800
  #define MDIO_AN_TX_VEND_STATUS1_RATE_MASK	GENMASK(3, 1)
-@@ -73,18 +73,6 @@
+@@ -73,18 +74,6 @@
  #define MDIO_AN_RX_VEND_STAT3			0xe832
  #define MDIO_AN_RX_VEND_STAT3_AFR		BIT(0)
  
@@ -1272,7 +1289,7 @@
  /* Vendor specific 1, MDIO_MMD_VEND1 */
  #define VEND1_GLOBAL_FW_ID			0x0020
  #define VEND1_GLOBAL_FW_ID_MAJOR		GENMASK(15, 8)
-@@ -124,31 +112,6 @@
+@@ -124,31 +113,6 @@
  #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2	BIT(1)
  #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3	BIT(0)
  
@@ -1304,7 +1321,7 @@
  static int aqr107_get_sset_count(struct phy_device *phydev)
  {
  	return AQR107_SGMII_STAT_SZ;
-@@ -422,7 +361,7 @@ static int aqr107_get_downshift(struct phy_device *phydev, u8 *data)
+@@ -398,7 +362,7 @@ static int aqr107_get_downshift(struct phy_device *phydev, u8 *data)
  	return 0;
  }
  
@@ -1313,7 +1330,7 @@
  {
  	int val = 0;
  
-@@ -482,7 +421,7 @@ static int aqr107_wait_reset_complete(struct phy_device *phydev)
+@@ -458,7 +422,7 @@ static int aqr107_wait_reset_complete(struct phy_device *phydev)
  	return val ? 0 : -ETIMEDOUT;
  }
  
@@ -1322,7 +1339,7 @@
  {
  	u8 fw_major, fw_minor, build_id, prov_id;
  	int val;
-@@ -505,6 +444,21 @@ static void aqr107_chip_info(struct phy_device *phydev)
+@@ -481,6 +445,21 @@ static void aqr107_chip_info(struct phy_device *phydev)
  		   fw_major, fw_minor, build_id, prov_id);
  }
  
@@ -1344,7 +1361,7 @@
  static int aqr107_config_init(struct phy_device *phydev)
  {
  	int ret;
-@@ -520,6 +470,12 @@ static int aqr107_config_init(struct phy_device *phydev)
+@@ -499,6 +478,12 @@ static int aqr107_config_init(struct phy_device *phydev)
  	ret = aqr107_wait_reset_complete(phydev);
  	if (!ret)
  		aqr107_chip_info(phydev);
@@ -1357,7 +1374,7 @@
  
  	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
  }
-@@ -604,12 +556,39 @@ static void aqr107_link_change_notify(struct phy_device *phydev)
+@@ -574,12 +559,41 @@ static void aqr107_link_change_notify(struct phy_device *phydev)
  
  static int aqr107_suspend(struct phy_device *phydev)
  {
@@ -1388,12 +1405,17 @@
 +							"aqr_firmware_heartbeat_thread");
 +		if (IS_ERR(priv->heartbeat_thread)) {
 +			phydev_err(phydev,
-+				   "Failed to create aqr_firmware_heartbeat_thread\n");
-+		}
-+		wake_up_process(priv->heartbeat_thread);
++				   "Failed to create aqr_firmware_heartbeat_thread(%ld)\n",
++				    PTR_ERR(priv->heartbeat_thread));
++			priv->heartbeat_thread = NULL;
++		} else
++			wake_up_process(priv->heartbeat_thread);
 +	}
 +	spin_unlock(&priv->lock);
 +#endif
  	return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
  				  MDIO_CTRL1_LPOWER);
  }
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/752-net-dsa-phy-coverity-scan.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2720-net-dsa-phy-coverity-scan.patch
old mode 100755
new mode 100644
similarity index 78%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/752-net-dsa-phy-coverity-scan.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2720-net-dsa-phy-coverity-scan.patch
index 17921e8..dfdb019
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/752-net-dsa-phy-coverity-scan.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2720-net-dsa-phy-coverity-scan.patch
@@ -1,7 +1,18 @@
-diff -Naur a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
---- a/drivers/net/dsa/mt7530.c	2022-11-25 14:10:39.452491570 +0800
-+++ b/drivers/net/dsa/mt7530.c	2022-11-28 09:47:11.157096408 +0800
-@@ -2476,7 +2476,7 @@
+From 98719219a038adac88f2fae9caaecb7e84704d09 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:32 +0800
+Subject: [PATCH] [networking][999-2720-net-dsa-phy-coverity-scan.patch]
+
+---
+ drivers/net/dsa/mt7530.c     |  4 ++-
+ drivers/net/dsa/mt7531_phy.c | 56 +++++++++++++++++++-----------------
+ 2 files changed, 32 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 290a2e77a..21fa3e300 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2477,7 +2477,7 @@ static int
  mt7531_cpu_port_config(struct dsa_switch *ds, int port)
  {
  	struct mt7530_priv *priv = ds->priv;
@@ -10,7 +21,7 @@
  	int speed;
  
  	switch (port) {
-@@ -2496,6 +2496,8 @@
+@@ -2497,6 +2497,8 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port)
  		priv->p6_interface = interface;
  		break;
  	};
@@ -19,10 +30,11 @@
  
  	if (interface == PHY_INTERFACE_MODE_2500BASEX)
  		speed = SPEED_2500;
-diff -Naur a/drivers/net/dsa/mt7531_phy.c b/drivers/net/dsa/mt7531_phy.c
---- a/drivers/net/dsa/mt7531_phy.c	2022-11-25 14:10:47.032465430 +0800
-+++ b/drivers/net/dsa/mt7531_phy.c	2022-11-29 09:56:05.024665073 +0800
-@@ -252,7 +252,7 @@
+diff --git a/drivers/net/dsa/mt7531_phy.c b/drivers/net/dsa/mt7531_phy.c
+index a5c1e7d54..aaa03c678 100644
+--- a/drivers/net/dsa/mt7531_phy.c
++++ b/drivers/net/dsa/mt7531_phy.c
+@@ -252,7 +252,7 @@ static int ge_cal_rext(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  	u16 dev1e_17a_tmp, dev1e_e0_tmp;
  
  	/* *** Iext/Rext Cal start ************ */
@@ -31,7 +43,7 @@
  	/* analog calibration enable, Rext calibration enable */
  	/* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
  	/* 1e_dc[0]:rg_txvos_calen */
-@@ -296,7 +296,7 @@
+@@ -296,7 +296,7 @@ static int ge_cal_rext(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  			all_ana_cal_status = ANACAL_FINISH;
  			//printk("  GE Rext AnaCal Done! (%d)(0x%x)  \r\n", cnt, rg_zcal_ctrl);
  		} else {
@@ -40,7 +52,7 @@
  			dev1e_e0_tmp =	tc_phy_read_dev_reg(ds, PHY0, 0x1e, 0xe0);
  			if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
  				all_ana_cal_status = ANACAL_SATURATION;  /* need to FT(IC fail?) */
-@@ -718,32 +718,34 @@
+@@ -718,32 +718,34 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  				} else if (phyaddr == 1) {
  					if (calibration_pair == ANACAL_PAIR_A)
  						tx_amp_temp = tx_amp_temp - 1;
@@ -91,7 +103,7 @@
  				}
  				reg_temp = tc_phy_read_dev_reg(ds,  phyaddr, 0x1e, tx_amp_reg)&(~0xff00);
  				tc_phy_write_dev_reg(ds, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
-@@ -858,7 +860,7 @@
+@@ -858,7 +860,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = 0x0000;
  					reg_backup |= ((tx_amp_temp << 10) | (tx_amp_temp << 0));
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x12, reg_backup);
@@ -100,7 +112,7 @@
  					//printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(ds,  phyaddr, 0x1e, 0x16);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -866,7 +868,7 @@
+@@ -866,7 +868,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (tx_amp_temp << 0);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x16, reg_backup);
@@ -109,7 +121,7 @@
  					//printk("PORT[%d] 1e.016 = %x (OFFSET_TESTMODE_1000M_PAIR_A)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_B){
-@@ -876,7 +878,7 @@
+@@ -876,7 +878,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = 0x0000;
                                         reg_backup |= ((tx_amp_temp << 8) | (tx_amp_temp << 0));
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x17, reg_backup);
@@ -118,7 +130,7 @@
  					//printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(ds,  phyaddr, 0x1e, 0x18);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -884,7 +886,7 @@
+@@ -884,7 +886,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (tx_amp_temp << 0);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x18, reg_backup);
@@ -127,7 +139,7 @@
  					//printk("PORT[%d] 1e.018 = %x (OFFSET_TESTMODE_1000M_PAIR_B)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_C){
-@@ -894,7 +896,7 @@
+@@ -894,7 +896,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f00));
  					reg_backup |= (tx_amp_temp << 8);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x19, reg_backup);
@@ -136,7 +148,7 @@
  					//printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(ds,  phyaddr, 0x1e, 0x20);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -902,7 +904,7 @@
+@@ -902,7 +904,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (tx_amp_temp << 0);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x20, reg_backup);
@@ -145,7 +157,7 @@
  					//printk("PORT[%d] 1e.020 = %x (OFFSET_TESTMODE_1000M_PAIR_C)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_D){
-@@ -912,7 +914,7 @@
+@@ -912,7 +914,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f00));
  					reg_backup |= (tx_amp_temp << 8);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x21, reg_backup);
@@ -154,7 +166,7 @@
  					//printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(ds,  phyaddr, 0x1e, 0x22);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -920,7 +922,7 @@
+@@ -920,7 +922,7 @@ static int ge_cal_tx_amp(struct dsa_switch *ds, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (tx_amp_temp << 0);
  					tc_phy_write_dev_reg(ds, phyaddr, 0x1e, 0x22, reg_backup);
@@ -163,7 +175,7 @@
  					//printk("PORT[%d] 1e.022 = %x (OFFSET_TESTMODE_1000M_PAIR_D)\n", phyaddr, reg_backup);
  				}
  
-@@ -1352,7 +1354,7 @@
+@@ -1352,7 +1354,7 @@ static void mt7531_eee_setting(struct dsa_switch *ds, u32 port)
  
  int mt7531_phy_setup(struct dsa_switch *ds)
  {
@@ -172,4 +184,6 @@
  	int i;
  
  	mt7531_phy_setting(ds);
- 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2721-net-mt753x-phy-coverity-scan.patch
old mode 100755
new mode 100644
similarity index 79%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2721-net-mt753x-phy-coverity-scan.patch
index c4d7d4c..a9b1316
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2721-net-mt753x-phy-coverity-scan.patch
@@ -1,7 +1,18 @@
-diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_common.c b/drivers/net/phy/mtk/mt753x/mt753x_common.c
---- a/drivers/net/phy/mtk/mt753x/mt753x_common.c	2022-11-25 14:12:06.308223474 +0800
-+++ b/drivers/net/phy/mtk/mt753x/mt753x_common.c	2022-11-25 14:21:52.038450276 +0800
-@@ -49,6 +49,9 @@
+From 520aea1caf199f454a0988f23d000c18256caa2b Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:32 +0800
+Subject: [PATCH] [networking][999-2721-net-mt753x-phy-coverity-scan.patch]
+
+---
+ drivers/net/phy/mtk/mt753x/mt753x_common.c |  3 ++
+ drivers/net/phy/mtk/mt753x/mt753x_phy.c    | 56 +++++++++++-----------
+ 2 files changed, 32 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/net/phy/mtk/mt753x/mt753x_common.c b/drivers/net/phy/mtk/mt753x/mt753x_common.c
+index 4015ddf12..0e08c8532 100644
+--- a/drivers/net/phy/mtk/mt753x/mt753x_common.c
++++ b/drivers/net/phy/mtk/mt753x/mt753x_common.c
+@@ -49,6 +49,9 @@ static void display_port_link_status(struct gsw_mt753x *gsw, u32 port)
  	case MAC_SPD_2500:
  		speed = "2.5Gbps";
  		break;
@@ -11,10 +22,11 @@
  	}
  
  	if (pmsr & MAC_LNK_STS) {
-diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_phy.c b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
---- a/drivers/net/phy/mtk/mt753x/mt753x_phy.c	2022-11-25 14:12:34.160149995 +0800
-+++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c	2022-11-29 14:12:28.261884707 +0800
-@@ -141,7 +141,7 @@
+diff --git a/drivers/net/phy/mtk/mt753x/mt753x_phy.c b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
+index 0c6f9c930..afc46cdd8 100644
+--- a/drivers/net/phy/mtk/mt753x/mt753x_phy.c
++++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
+@@ -141,7 +141,7 @@ int ge_cal_rext(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  	u16 dev1e_17a_tmp, dev1e_e0_tmp;
  
  	/* *** Iext/Rext Cal start ************ */
@@ -23,7 +35,7 @@
  	/* analog calibration enable, Rext calibration enable */
  	/* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
  	/* 1e_dc[0]:rg_txvos_calen */
-@@ -185,7 +185,7 @@
+@@ -185,7 +185,7 @@ int ge_cal_rext(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  			all_ana_cal_status = ANACAL_FINISH;
  			//printk("  GE Rext AnaCal Done! (%d)(0x%x)  \r\n", cnt, rg_zcal_ctrl);
  		} else {
@@ -32,7 +44,7 @@
  			dev1e_e0_tmp =	tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0);
  			if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
  				all_ana_cal_status = ANACAL_SATURATION;  /* need to FT(IC fail?) */
-@@ -580,33 +580,35 @@
+@@ -580,33 +580,35 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  				} else if (phyaddr == 1) {
  					if (calibration_pair == ANACAL_PAIR_A)
  						tx_amp_temp = tx_amp_temp - 1;
@@ -85,7 +97,7 @@
  				reg_temp = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, tx_amp_reg)&(~0xff00);
  				tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg_100,(tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
  				tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg, (tx_amp_temp|((tx_amp_temp)<<tx_amp_reg_shift)));
-@@ -704,7 +706,7 @@
+@@ -704,7 +706,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
                                         reg_backup = 0x0000;
                                         reg_backup |= ((reg_tmp << 10) | (reg_tmp << 0));
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x12, reg_backup);
@@ -94,7 +106,7 @@
  					//printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x16);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -712,7 +714,7 @@
+@@ -712,7 +714,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (reg_tmp << 0);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x16, reg_backup);
@@ -103,7 +115,7 @@
  					//printk("PORT[%d] 1e.016 = %x (OFFSET_TESTMODE_1000M_PAIR_A)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_B){
-@@ -722,7 +724,7 @@
+@@ -722,7 +724,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
                                         reg_backup = 0x0000;
                                         reg_backup |= ((reg_tmp << 8) | (reg_tmp << 0));
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x17, reg_backup);
@@ -112,7 +124,7 @@
  					//printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x18);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -730,7 +732,7 @@
+@@ -730,7 +732,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (reg_tmp << 0);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18, reg_backup);
@@ -121,7 +133,7 @@
  					//printk("PORT[%d] 1e.018 = %x (OFFSET_TESTMODE_1000M_PAIR_B)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_C){
-@@ -740,7 +742,7 @@
+@@ -740,7 +742,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f00));
  					reg_backup |= (reg_tmp << 8);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x19, reg_backup);
@@ -130,7 +142,7 @@
  					//printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x20);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -748,7 +750,7 @@
+@@ -748,7 +750,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (reg_tmp << 0);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x20, reg_backup);
@@ -139,7 +151,7 @@
  					//printk("PORT[%d] 1e.020 = %x (OFFSET_TESTMODE_1000M_PAIR_C)\n", phyaddr, reg_backup);
  				}
  				else if(calibration_pair == ANACAL_PAIR_D){
-@@ -758,7 +760,7 @@
+@@ -758,7 +760,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f00));
  					reg_backup |= (reg_tmp << 8);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x21, reg_backup);
@@ -148,7 +160,7 @@
  					//printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
  					reg_backup = tc_phy_read_dev_reg(gsw,  phyaddr, 0x1e, 0x22);
  					reg_tmp = ((reg_backup & 0x3f) >> 0);
-@@ -766,7 +768,7 @@
+@@ -766,7 +768,7 @@ int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
  					reg_backup = (reg_backup & (~0x3f));
  					reg_backup |= (reg_tmp << 0);
  					tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x22, reg_backup);
@@ -157,3 +169,6 @@
  					//printk("PORT[%d] 1e.022 = %x (OFFSET_TESTMODE_1000M_PAIR_D)\n", phyaddr, reg_backup);
  				}
  
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2722-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2722-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch
new file mode 100644
index 0000000..8e87e12
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2722-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch
@@ -0,0 +1,24 @@
+From 14155ead210d465dc00552fa2537bdafc25054a5 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:33 +0800
+Subject: [PATCH] 
+ [networking][999-2722-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch]
+
+---
+ include/dt-bindings/phy/phy.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
+index b6a1eaf1b..1f3f866fa 100644
+--- a/include/dt-bindings/phy/phy.h
++++ b/include/dt-bindings/phy/phy.h
+@@ -16,5 +16,6 @@
+ #define PHY_TYPE_USB2		3
+ #define PHY_TYPE_USB3		4
+ #define PHY_TYPE_UFS		5
++#define PHY_TYPE_DP		6
+ 
+ #endif /* _DT_BINDINGS_PHY */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2723-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2723-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch
new file mode 100644
index 0000000..c0e2127
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2723-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch
@@ -0,0 +1,24 @@
+From 971fc691db21a6d231545f8519d920301818c2d5 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:33 +0800
+Subject: [PATCH] 
+ [networking][999-2723-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch]
+
+---
+ include/dt-bindings/phy/phy.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
+index 1f3f866fa..3727ef721 100644
+--- a/include/dt-bindings/phy/phy.h
++++ b/include/dt-bindings/phy/phy.h
+@@ -17,5 +17,6 @@
+ #define PHY_TYPE_USB3		4
+ #define PHY_TYPE_UFS		5
+ #define PHY_TYPE_DP		6
++#define PHY_TYPE_XPCS		7
+ 
+ #endif /* _DT_BINDINGS_PHY */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch
new file mode 100644
index 0000000..41db424
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch
@@ -0,0 +1,24 @@
+From 313a776ae1ef71f826cd39545e358a3735c1a032 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:33 +0800
+Subject: [PATCH] 
+ [networking][999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch]
+
+---
+ include/dt-bindings/phy/phy.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
+index 3727ef721..36e8c241c 100644
+--- a/include/dt-bindings/phy/phy.h
++++ b/include/dt-bindings/phy/phy.h
+@@ -18,5 +18,6 @@
+ #define PHY_TYPE_UFS		5
+ #define PHY_TYPE_DP		6
+ #define PHY_TYPE_XPCS		7
++#define PHY_TYPE_SGMII		8
+ 
+ #endif /* _DT_BINDINGS_PHY */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9010-iwconfig-wireless-rate-fix.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2725-iwconfig-wireless-rate-fix.patch
similarity index 63%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9010-iwconfig-wireless-rate-fix.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2725-iwconfig-wireless-rate-fix.patch
index b29e4cc..951afc2 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9010-iwconfig-wireless-rate-fix.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2725-iwconfig-wireless-rate-fix.patch
@@ -1,20 +1,34 @@
---- a/include/uapi/linux/wireless.h

-+++ b/include/uapi/linux/wireless.h

-@@ -678,7 +678,7 @@

-  *	Generic format for most parameters that fit in an int

-  */

- struct iw_param {

--  __s32		value;		/* The value of the parameter itself */

-+  __u64		value;		/* The value of the parameter itself */

-   __u8		fixed;		/* Hardware should not use auto select */

-   __u8		disabled;	/* Disable the feature */

-   __u16		flags;		/* Various specifc flags (if any) */

-@@ -1002,7 +1002,7 @@ struct iw_range {

- 

- 	/* Rates */

- 	__u8		num_bitrates;	/* Number of entries in the list */

--	__s32		bitrate[IW_MAX_BITRATES];	/* list, in bps */

-+	__u64		bitrate[IW_MAX_BITRATES];	/* list, in bps */

- 

- 	/* RTS threshold */

- 	__s32		min_rts;	/* Minimal RTS threshold */

+From 572be3e7a2e9f41c64dd6c8c89cc763b97ecab6c Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:33 +0800
+Subject: [PATCH] [networking][999-2725-iwconfig-wireless-rate-fix.patch]
+
+---
+ include/uapi/linux/wireless.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/uapi/linux/wireless.h b/include/uapi/linux/wireless.h
+index 24f3371ad..590c90b14 100644
+--- a/include/uapi/linux/wireless.h
++++ b/include/uapi/linux/wireless.h
+@@ -678,7 +678,7 @@
+  *	Generic format for most parameters that fit in an int
+  */
+ struct iw_param {
+-  __s32		value;		/* The value of the parameter itself */
++  __u64		value;		/* The value of the parameter itself */
+   __u8		fixed;		/* Hardware should not use auto select */
+   __u8		disabled;	/* Disable the feature */
+   __u16		flags;		/* Various specifc flags (if any) */
+@@ -1002,7 +1002,7 @@ struct iw_range {
+ 
+ 	/* Rates */
+ 	__u8		num_bitrates;	/* Number of entries in the list */
+-	__s32		bitrate[IW_MAX_BITRATES];	/* list, in bps */
++	__u64		bitrate[IW_MAX_BITRATES];	/* list, in bps */
+ 
+ 	/* RTS threshold */
+ 	__s32		min_rts;	/* Minimal RTS threshold */
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2800-misc-add-mtk-platform.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2800-misc-add-mtk-platform.patch
new file mode 100644
index 0000000..19cab49
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2800-misc-add-mtk-platform.patch
@@ -0,0 +1,32 @@
+From cbf9eb1b168ed4b650d464512f6502d3d1668813 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:34 +0800
+Subject: [PATCH] [misc][999-2800-misc-add-mtk-platform.patch]
+
+---
+ drivers/misc/Kconfig  | 1 +
+ drivers/misc/Makefile | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index c55b63750..4cd30fab5 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -481,4 +481,5 @@ source "drivers/misc/cxl/Kconfig"
+ source "drivers/misc/ocxl/Kconfig"
+ source "drivers/misc/cardreader/Kconfig"
+ source "drivers/misc/habanalabs/Kconfig"
++source "drivers/misc/mediatek/Kconfig"
+ endmenu
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index c1860d35d..30b5d29a1 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -57,3 +57,4 @@ obj-y				+= cardreader/
+ obj-$(CONFIG_PVPANIC)   	+= pvpanic.o
+ obj-$(CONFIG_HABANA_AI)		+= habanalabs/
+ obj-$(CONFIG_XILINX_SDFEC)	+= xilinx_sdfec.o
++obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch
new file mode 100644
index 0000000..d12f629
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch
@@ -0,0 +1,38 @@
+From 9ec485a8a2002d6625b8b43158887ecac572ce76 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:34 +0800
+Subject: [PATCH] 
+ [uncategorized][999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch]
+
+---
+ arch/arm64/boot/dts/mediatek/mt7622.dtsi | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+index 988c31403..d7f147414 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -568,6 +568,20 @@
+ 		status = "disabled";
+ 	};
+ 
++	snand: snfi@1100d000 {
++		compatible = "mediatek,mt7622-snand";
++		reg = <0 0x1100d000 0 0x1000>, <0 0x1100e000 0 0x1000>;
++		reg-names = "nfi", "ecc";
++		interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
++		clocks = <&pericfg CLK_PERI_NFI_PD>,
++			 <&pericfg CLK_PERI_SNFI_PD>,
++			 <&pericfg CLK_PERI_NFIECC_PD>;
++		clock-names = "nfi_clk", "pad_clk", "ecc_clk";
++		#address-cells = <1>;
++		#size-cells = <0>;
++		status = "disabled";
++	};
++
+ 	nor_flash: spi@11014000 {
+ 		compatible = "mediatek,mt7622-nor",
+ 			     "mediatek,mt8173-nor";
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2901-dts-mt7622-remove-cooling-device.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2901-dts-mt7622-remove-cooling-device.patch
new file mode 100644
index 0000000..16bf5b8
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2901-dts-mt7622-remove-cooling-device.patch
@@ -0,0 +1,43 @@
+From abe2d8053a5323638eedb60e1e58d2bf34b98a3b Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Fri, 2 Jun 2023 13:06:34 +0800
+Subject: [PATCH] 
+ [uncategorized][999-2901-dts-mt7622-remove-cooling-device.patch]
+
+---
+ arch/arm64/boot/dts/mediatek/mt7622.dtsi | 19 -------------------
+ 1 file changed, 19 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+index d7f147414..753a97a2f 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -167,25 +167,6 @@
+ 				};
+ 			};
+ 
+-			cooling-maps {
+-				map0 {
+-					trip = <&cpu_passive>;
+-					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+-							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+-				};
+-
+-				map1 {
+-					trip = <&cpu_active>;
+-					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+-							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+-				};
+-
+-				map2 {
+-					trip = <&cpu_hot>;
+-					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+-							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+-				};
+-			};
+ 		};
+ 	};
+ 
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index 2a6b31a..e21e5f5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -1,27 +1,13 @@
 #patch patches-5.4 (come from openwrt/lede/target/linux/mediatek)
 SRC_URI_append = " \
-    file://0001-clk-mtk-add-mt7986-support.patch \
-    file://0001-cpufreq-add-the-missing-platform-driver-unregister.patch \
     file://0001-v5.7-spi-make-spi-max-frequency-optional.patch \
-    file://0002-clk-mtk-add-mt7981-support.patch \
-    file://0002-cpufreq-Enable-clocks-and-regulators.patch \
     file://0002-v5.7-spi-add-support-for-mediatek-spi-nor-controller.patch \
-    file://0003-clk-mtk-add-mt7988-support.patch \
-    file://0003-cpufreq-add-mt7988a-spim-snand-support.patch \
     file://0003-switch-add-mt7531.patch \
-    file://0005-clk-mtk-add-chg-shift-control.patch \
     file://0005-dts-mt7622-add-gsw.patch \
     file://0005-dts-mt7629-add-gsw.patch \
     file://0006-dts-fix-bpi2-console.patch \
     file://0006-dts-fix-bpi64-console.patch \
-    file://0006-powerdomain-add-mt7988-support.patch \
-    file://0007-cpufreq-mtk-vbining-add-mt7988-support.patch \
     file://0010-dts-mt7629-rfb-fix-firmware-partition.patch \
-    file://0020-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
-    file://0021-dts-mt7622-remove-cooling-device.patch \
-    file://0100-hwnat_Kconfig_Makefile.patch \
-    file://0111-mt7986-trng-add-rng-support.patch \
-    file://0200-show_model_name_in_cpuinfo_on_arm64.patch \
     file://0226-phy-phy-mtk-tphy-Add-hifsys-support.patch \
     file://0227-arm-dts-Add-Unielec-U7623-DTS.patch \
     file://0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch \
@@ -29,122 +15,136 @@
     file://0307-dts-mt7629-add-snand-support.patch \
     file://0308-dts-mt7622-add-snand-support.patch \
     file://0310-dts-add-wmac-support-for-mt7622-rfb1.patch \
-    file://0322-fix-dirty-race-between-do_tmpfile.patch \
-    file://0400-sound-add-some-helpers-to-control-mtk_memif.patch \
-    file://0401-sound-refine-hw-params-and-hw-prepare.patch \
-    file://0402-sound-add-mt7986-driver.patch \
-    file://0490-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch \
-    file://0491-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch \
     file://0500-v5.6-crypto-backport-inside-secure.patch \
     file://0501-crypto-add-eip97-inside-secure-support.patch \
     file://0502-dts-mt7623-eip97-inside-secure-support.patch \
     file://0503-crypto-fix-eip97-cache-incoherent.patch \
-    file://0504-macsec-revert-async-support.patch \
-    file://0505-crypto-add-eip197-inside-secure-support.patch \
     file://0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch;apply=no \
     file://0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch \
     file://0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch \
     file://0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch \
     file://0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch \
     file://0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch \
-    file://0666-add-spimem-support-to-mtk-spi.patch \
-    file://0666-spi-mtk-nor-fix-timeout-calculation-overflow.patch \
-    file://0667-spi-mediatek-fix-timeout-for-large-data.patch \
-    file://0668-spi-mediatek-fix-dma-unmap-twice.patch \
-    file://0669-fix-SPIM-NAND-and-NOR-probing.patch \
-    file://0670-fix-SPIM-dma-buffer-not-aligned.patch \
-    file://0701-fix-mtk-nfi-driver-dependency.patch \
-    file://0801-mtk-sd-add-mt7986-support.patch \
-    file://0802-mtk-sd-Add-subsys-clock-control.patch \
     file://0900-bt-mtk-serial-fix.patch \
-    file://0900-i2c-busses-add-mt7986-support.patch \
-    file://0901-i2c-busses-add-mt7981-support.patch \
-    file://0920-kernel-MT7988-fix-spi-dma-unmap.patch \
-    file://0930-pwm-add-mt7986-support.patch \
-    file://0931-pwm-add-mt7981-support.patch \
-    file://0932-add-pwm-feature-in-mt7988-project.patch \
-    file://0950-add-pmic-config.patch \
-    file://0950-pwm-mediatek-add-longer-period-support.patch \
-    file://0960-watchdog-add-mt7986-assert.patch \
-    file://0961-dual-image-mount-rootfs.patch \
     file://0990-gsw-rtl8367s-mt7622-support.patch \
     file://0991-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch \
     file://0992-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch \
     file://0993-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch \
     file://0994-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch \
-    file://1001-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch \
     file://1003-dts-mt7622-rfb-change-to-ax-mtd-layout.patch \
     file://1010-pcie-mediatek-fix-clearing-interrupt-status.patch \
-    file://1015-pcie-add-pcie-gen3-upstream-driver.patch \
     file://1020-spi-nor-w25q512jv.patch \
     file://1021-ubnt-ledbar-driver.patch \
-    file://1023-kgdb-add-interrupt-control.patch \
-    file://1024-pcie-add-multi-MSI-support.patch \
-    file://1661-Add-trngv2-driver-support.patch \
-    file://1662-trng-Add-trng-support-for-mt7988.patch \
-    file://2000-misc-add-mtk-platform.patch \
-    file://400-mtd-add-mtk-snand-driver.patch \
-    file://401-pinctrl-add-mt7986-driver.patch \
-    file://401-pinctrl-enable-mt7988-pinctrl-config.patch \
-    file://402-pinctrl-add-mt7981-driver.patch \
-    file://412-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch \
-    file://413-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch \
-    file://414-mtd-spinand-fix-gigadevice-read-dummy.patch \
-    file://415-mtd-spinand-fix-F50L1G41LB-ecc-check.patch \
-    file://416-mtd-spinor-support-EN25QX128A.patch \
-    file://492-mtd-tests-fix-pagetest-load.patch \
-    file://500-auxadc-add-auxadc-32k-clk.patch \
-    file://6001-mtk-thermal-add-lvts-support.patch \
-    file://7000-fix-race-inside-napi-enable.patch \
-    file://7001-net-make-napi-disable-symmetric-with-enable.patch \
-    file://7002-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch \
-    file://730-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch \
-    file://738-mt7531-gsw-internal_phy_calibration.patch;apply=no \
-    file://739-mt7531-gsw-port5_external_phy_init.patch;apply=no \
-    file://740-add-gpy211-phy-support.patch \
-    file://741-add-default-setting-to-dsa-unused-port.patch \
-    file://742-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch \
-    file://744-en8811h-2p5gphy-support.patch \
-    file://745-en8801sc-gphy-support.patch \
-    file://745-mdiobus-add-c45.patch \
-    file://746-add-mediatek-2p5ge-phy-support.patch \
-    file://746-mxl-gpy-phy-support.patch \
-    file://747-net-phy-aquantia-add-AQR113C.patch \
-    file://748-add-netlink-support-for-dsa.patch \
-    file://749-net-dsa-support-mt7988.patch \
-    file://750-add-mdio-bus-for-gphy-calibration.patch \
-    file://751-net-phy-aquantia-add-firmware-download.patch \
-    file://752-net-dsa-phy-coverity-scan.patch \
-    file://753-net-mt753x-phy-coverity-scan.patch;apply=no \
-    file://754-net-phy-add-5GBASER.patch \
-    file://755-net-phy-sfp-add-rollball-support.patch \
-    file://757-net-phy-add-phylink-pcs-support.patch;apply=no \
-    file://758-net-phy-add-phylink-pcs-decode-helper.patch \
-    file://8000-PATCH-1-4-tphy-support-type-switch-by-pericfg.patch \
-    file://8001-PATCH-2-4-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch \
-    file://8002-PATCH-3-4-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch \
-    file://8003-PATCH-4-4-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch \
-    file://8004-nvmem-core-Add-functions-to-make-number-reading-easy.patch \
-    file://8005-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch \
-    file://8006-phy-phy-mtk-tphy-add-support-efuse-setting.patch \
-    file://8007-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch \
-    file://8008-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch \
-    file://8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch \
-    file://8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch \
-    file://8011-ovs-add-multicast-to-unicast-support.patch \
-    file://9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch \
-    file://9001-PATCH-1-2-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch \
-    file://9002-PATCH-1-1-usb-add-embedded-Host-feature-support.patch \
-    file://9009-Add-spi-runtime-PM-support.patch \
-    file://9010-iwconfig-wireless-rate-fix.patch;apply=no \
-    file://9011-Modify-tick_delay-for-spi-work-safety.patch \
-    file://9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch \
-    file://9014-drivers-spi-Add-support-for-dynamic-calibration.patch \
-    file://9015-drivers-spi-mem-Add-spi-calibration-hook.patch \
-    file://9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch \
-    file://9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch \
-    file://9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch \
-    file://9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch \
-    file://9102-spi-update-driver.patch \
-    file://9103-drivers-spi-mt65xx-add-dts-buswidth-flow.patch \
+    file://999-1600-mdiobus-add-c45.patch \
+    file://999-1700-macsec-revert-async-support.patch \
+    file://999-1701-add-default-setting-to-dsa-unused-port.patch \
+    file://999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch \
+    file://999-1703-mxl-gpy-phy-support.patch \
+    file://999-1704-net-phy-aquantia-add-AQR113C.patch \
+    file://999-1705-add-netlink-support-for-dsa.patch \
+    file://999-1706-net-dsa-support-mt7988.patch \
+    file://999-1707-add-mdio-bus-for-gphy-calibration.patch \
+    file://999-1708-net-phy-add-5GBASER.patch \
+    file://999-1709-net-phy-sfp-add-rollball-support.patch \
+    file://999-1710-net-phy-add-phylink-pcs-support.patch;apply=no \
+    file://999-1711-net-phy-add-phylink-pcs-decode-helper.patch \
+    file://999-1712-net-phy-add-phylink-rate-matching-support.patch;apply=no \
+    file://999-2000-show_model_name_in_cpuinfo_on_arm64.patch \
+    file://999-2001-kgdb-add-interrupt-control.patch \
+    file://999-2010-clk-mtk-add-mt7986-support.patch \
+    file://999-2011-clk-mtk-add-mt7981-support.patch \
+    file://999-2012-clk-mtk-add-mt7988-support.patch \
+    file://999-2013-clk-mtk-add-chg-shift-control.patch \
+    file://999-2020-pinctrl-add-mt7986-driver.patch \
+    file://999-2021-pinctrl-enable-mt7988-pinctrl-config.patch \
+    file://999-2022-pinctrl-add-mt7981-driver.patch \
+    file://999-2040-powerdomain-add-mt7988-support.patch \
+    file://999-2050-watchdog-add-mt7986-assert.patch \
+    file://999-2100-mt7986-trng-add-rng-support.patch \
+    file://999-2101-Add-trngv2-driver-support.patch \
+    file://999-2102-trng-Add-trng-support-for-mt7988.patch \
+    file://999-2103-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch \
+    file://999-2110-i2c-busses-add-mt7986-support.patch \
+    file://999-2111-i2c-busses-add-mt7981-support.patch \
+    file://999-2120-auxadc-add-auxadc-32k-clk.patch \
+    file://999-2130-pwm-add-mt7986-support.patch \
+    file://999-2131-pwm-add-mt7981-support.patch \
+    file://999-2132-add-pwm-feature-in-mt7988-project.patch \
+    file://999-2133-pwm-mediatek-add-longer-period-support.patch \
+    file://999-2140-mtk-thermal-add-lvts-support.patch \
+    file://999-2150-sound-add-some-helpers-to-control-mtk_memif.patch \
+    file://999-2151-sound-refine-hw-params-and-hw-prepare.patch \
+    file://999-2152-sound-add-mt7986-driver.patch \
+    file://999-2300-mtk-sd-add-mt7986-support.patch \
+    file://999-2301-mtk-sd-Add-subsys-clock-control.patch \
+    file://999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch \
+    file://999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch \
+    file://999-2332-mtd-add-mtk-snand-driver.patch \
+    file://999-2333-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch \
+    file://999-2334-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch \
+    file://999-2335-mtd-spinand-fix-gigadevice-read-dummy.patch \
+    file://999-2336-mtd-spinand-fix-F50L1G41LB-ecc-check.patch \
+    file://999-2337-mtd-spinor-support-EN25QX128A.patch \
+    file://999-2338-mtd-tests-fix-pagetest-load.patch \
+    file://999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch \
+    file://999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch \
+    file://999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch \
+    file://999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch \
+    file://999-2361-add-spimem-support-to-mtk-spi.patch \
+    file://999-2362-spi-mtk-nor-fix-timeout-calculation-overflow.patch \
+    file://999-2363-spi-mediatek-fix-timeout-for-large-data.patch \
+    file://999-2364-spi-mediatek-fix-dma-unmap-twice.patch \
+    file://999-2365-fix-SPIM-NAND-and-NOR-probing.patch \
+    file://999-2366-fix-SPIM-dma-buffer-not-aligned.patch \
+    file://999-2367-fix-mtk-nfi-driver-dependency.patch \
+    file://999-2368-kernel-MT7988-fix-spi-dma-unmap.patch \
+    file://999-2369-Add-spi-runtime-PM-support.patch \
+    file://999-2370-Modify-tick_delay-for-spi-work-safety.patch \
+    file://999-2371-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch \
+    file://999-2372-drivers-spi-Add-support-for-dynamic-calibration.patch \
+    file://999-2373-drivers-spi-mem-Add-spi-calibration-hook.patch \
+    file://999-2374-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch \
+    file://999-2375-spi-update-driver.patch \
+    file://999-2376-drivers-spi-mt65xx-add-dts-buswidth-flow.patch \
+    file://999-2380-fix-dirty-race-between-do_tmpfile.patch \
+    file://999-2500-cpufreq-add-the-missing-platform-driver-unregister.patch \
+    file://999-2501-cpufreq-Enable-clocks-and-regulators.patch \
+    file://999-2502-cpufreq-add-mt7988a-spim-snand-support.patch \
+    file://999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch \
+    file://999-2530-add-pmic-config.patch \
+    file://999-2550-dual-image-mount-rootfs.patch \
+    file://999-2600-pcie-add-pcie-gen3-upstream-driver.patch \
+    file://999-2601-pcie-add-multi-MSI-support.patch \
+    file://999-2610-tphy-support-type-switch-by-pericfg.patch \
+    file://999-2611-phy-phy-mtk-tphy-add-support-efuse-setting.patch \
+    file://999-2612-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch \
+    file://999-2613-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch \
+    file://999-2614-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch \
+    file://999-2615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch \
+    file://999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch \
+    file://999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch \
+    file://999-2622-usb-add-embedded-Host-feature-support.patch \
+    file://999-2704-en8811h-2p5gphy-support.patch \
+    file://999-2705-hwnat_Kconfig_Makefile.patch \
+    file://999-2706-crypto-add-eip197-inside-secure-support.patch \
+    file://999-2707-mtkhnat-ipv6-fix-pskb-expand-head-limitation.patch \
+    file://999-2709-fix-race-inside-napi-enable.patch \
+    file://999-2710-net-make-napi-disable-symmetric-with-enable.patch \
+    file://999-2711-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch \
+    file://999-2712-net-ethernet-mtk_eth_soc-add-mtk-dsa-tag-rx-offload.patch \
+    file://999-2713-mt7531-gsw-internal_phy_calibration.patch;apply=no \
+    file://999-2714-mt7531-gsw-port5_external_phy_init.patch;apply=no \
+    file://999-2715-add-gpy211-phy-support.patch \
+    file://999-2716-en8801sc-gphy-support.patch \
+    file://999-2717-add-mediatek-2p5ge-phy-support.patch \
+    file://999-2719-net-phy-aquantia-add-firmware-download.patch \
+    file://999-2720-net-dsa-phy-coverity-scan.patch \
+    file://999-2721-net-mt753x-phy-coverity-scan.patch;apply=no \
+    file://999-2722-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch \
+    file://999-2723-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch \
+    file://999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch \
+    file://999-2725-iwconfig-wireless-rate-fix.patch;apply=no \
+    file://999-2800-misc-add-mtk-platform.patch \
+    file://999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
+    file://999-2901-dts-mt7622-remove-cooling-device.patch \
     "
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch
new file mode 100644
index 0000000..bccc43e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch
@@ -0,0 +1,3720 @@
+From 400f8349a31ffc48538aa7df64a88111de9a738b Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Thu, 13 Apr 2023 15:51:08 +0800
+Subject: [PATCH] mtk:wed:add wed3 support
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ 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   |   13 +-
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 1164 +++++++++++++----
+ drivers/net/ethernet/mediatek/mtk_wed.h       |   25 +-
+ .../net/ethernet/mediatek/mtk_wed_debugfs.c   |  584 ++++++++-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c   |   13 +-
+ 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          |   81 +-
+ 16 files changed, 1446 insertions(+), 333 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 364deef..f9a0120 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+@@ -191,44 +191,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 {
+@@ -238,15 +243,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 {
+@@ -254,31 +269,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 {
+@@ -827,6 +864,7 @@
+ 					 <&topckgen CK_TOP_CB_SGM_325M>;
+ 		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 7db5164..0a6db8b 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
+@@ -341,9 +341,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 67c6508..c407b33 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
+@@ -325,9 +325,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 388982c..d59c29f 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -4709,7 +4709,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 a9feaed..70e8377 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -605,9 +605,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 bc13a9b..3910163
+--- 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"
+@@ -396,7 +397,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);
+@@ -408,6 +409,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;
+@@ -443,6 +447,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 = rt_tos2priority(dscp) & 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 df10040..9e7d5aa 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);
+ int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index 9bc0857..86fc9a1 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
+@@ -458,8 +461,8 @@ 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;
++	/*if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
++		return err;*/
+ 
+ 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ 	if (!entry)
+@@ -499,8 +502,8 @@ clear:
+ 	mtk_foe_entry_clear(eth->ppe[i], 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 37a86c3..e3809db 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,25 @@ 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->rx_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->rx_ring[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);
++	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 +645,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 +655,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 +666,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 +685,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 +718,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 +741,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 +828,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 +989,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 +1027,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 +1060,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);
+@@ -728,73 +1086,97 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ 	mutex_unlock(&hw_lock);
+ }
+ 
++#define IRQ_MASK_APMCU		0x1000301c
+ 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;
++		unsigned long addr;
++		u32 value;
+ 
+-	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));
++		if (dev->hw->version < 3 || dev->hw->index) {
++			wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
++				FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
++		} else {
++			/* set mask apmcu */
++			addr = (unsigned long)ioremap(IRQ_MASK_APMCU, 4);
++			value = readl((void *)addr);
++			value |= 0x7;
++			writel(value, (void *)addr);
++			iounmap((void *)addr);
++		}
+ 
+ 		/* 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);
++			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_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);
+-
+-		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);
++			wed_w32(dev, MTK_WED_WPDMA_RX_RING1,  dev->wlan.wpdma_rx + 0x10);
++
++			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 +1188,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 +1293,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 +1311,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 +1359,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 +1409,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 +1442,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 +1466,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 +1564,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 +1702,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 +1730,31 @@ 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_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 +1765,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 +1848,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,13 +1873,87 @@ 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)
+@@ -1437,7 +1964,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ 	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 +1975,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 +2040,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 +2075,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 +2123,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 +2164,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;
+ 
+ 	/*
+@@ -1652,6 +2217,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)
+ {
+@@ -1660,6 +2348,8 @@ 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->version == 3)
++		val &= MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
+ 	WARN_RATELIMIT(val, "mtk_wed%d: error status=%08x\n",
+ 		       dev->hw->index, val);
+ 
+@@ -1752,6 +2442,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,
+@@ -1763,6 +2456,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;
+@@ -1802,9 +2496,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,
+@@ -1819,7 +2514,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 96e30a3..055594d 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+@@ -242,7 +242,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ 	u32 ofs = 0;
+ 	u32 boot_cr, val;
+ 
+-	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)
+@@ -289,8 +289,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 */
+@@ -298,8 +302,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 19e1199..c07bdb6 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+@@ -16,8 +16,9 @@
+ #define WARP_OK_STATUS (0)
+ #define WARP_ALREADY_DONE_STATUS (1)
+ 
+-#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..4e619ff 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 58b5ce6..5e51790 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -873,6 +873,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..60336e0 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;
+@@ -142,9 +163,13 @@ struct mtk_wed_device {
+ 		u32 wpdma_txfree;
+ 		u32 wpdma_rx_glo;
+ 		u32 wpdma_rx;
++		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/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch
new file mode 100644
index 0000000..3837d8d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch
@@ -0,0 +1,611 @@
+From 7304ce8edabcbc34433307b02de429c2d118abaa Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Tue, 23 May 2023 11:19:30 +0800
+Subject: [PATCH] mtk-wed-add-wed3-ser-support
+
+---
+ drivers/net/ethernet/mediatek/mtk_wed.c      | 236 +++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h |  73 +++++-
+ include/linux/soc/mediatek/mtk_wed.h         |   6 +-
+ 3 files changed, 291 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index 6ed1c83..990888d 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -99,11 +99,65 @@ 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);
+ 
+@@ -121,13 +175,62 @@ 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++)
+@@ -903,7 +1006,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 |
+@@ -1477,13 +1580,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);
+@@ -1511,6 +1631,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,
+@@ -1518,8 +1656,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 */
+@@ -1527,8 +1670,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 */
+@@ -1546,9 +1694,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,
+@@ -1565,6 +1721,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);
+ }
+ 
+ 
+@@ -1598,18 +1757,40 @@ 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);
++
++			/*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,
+@@ -1624,9 +1805,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);
+ 
+@@ -1635,18 +1822,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 |
+@@ -1659,7 +1848,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ 		}
+ 	}
+ 
+-	if (dev->ver > MTK_WED_V1) {
++	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)) {
+ 		dev->init_done = false;
+ 		mtk_wed_rx_reset(dev);
+ 	}
+@@ -1874,7 +2069,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;
+ 
+@@ -1884,6 +2079,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 2b389e8..bb02ba5 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/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/filogic_rdkb.cfg b/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/filogic_rdkb.cfg
index 83d27c8..d8f9ad1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/filogic_rdkb.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/filogic_rdkb.cfg
@@ -21,4 +21,6 @@
 CONFIG_OID_REGISTRY=m
 CONFIG_DEBUG_INFO=y
 CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_UNCOMPRESSED=y
\ No newline at end of file
+CONFIG_KALLSYMS_UNCOMPRESSED=y
+CONFIG_IP_MROUTE=y
+CONFIG_IPV6_MROUTE=y
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index 8728f3f..f6e8bc0 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -5,6 +5,7 @@
 FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}/mediatek/patches-5.4:"
 FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}/mediatek/flow_patch:"
 FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}/mediatek/nf_hnat:"
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}/mediatek/wed3:"
 
 KBRANCH ?= "linux-5.4.y"
 
@@ -46,7 +47,7 @@
     ${@bb.utils.contains('DISTRO_FEATURES','emmc','file://rdkb_cfg/emmc.cfg','',d)} \
 "
 
-SRC_URI_append_mt7986 += " \
+SRC_URI_append += " \
     ${@bb.utils.contains('DISTRO_FEATURES','flow_offload','file://rdkb_cfg/bridge_netfilter.cfg','',d)} \
 "
 
@@ -63,7 +64,7 @@
 require ${PN}-${PV}/mediatek/patches-5.4/patches-5.4.inc
 
 SRC_URI_remove_mt7986-32bit = " \
-    file://401-pinctrl-add-mt7986-driver.patch \
+    file://999-2020-pinctrl-add-mt7986-driver.patch \
     "
 SRC_URI_append_secureboot += " \
     file://0404-mtdsplit-dm-verity.patch;apply=no \
@@ -88,12 +89,13 @@
             patch -p1 < ${WORKDIR}/001-rdkb-eth-mtk-change-ifname-for.patch
             patch -p1 < ${WORKDIR}/003-rdkb-mtd-kernel-ubi-relayout.patch
             patch -p1 < ${WORKDIR}/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch
-            patch -p1 < ${WORKDIR}/738-mt7531-gsw-internal_phy_calibration.patch
-            patch -p1 < ${WORKDIR}/739-mt7531-gsw-port5_external_phy_init.patch
-            patch -p1 < ${WORKDIR}/753-net-mt753x-phy-coverity-scan.patch
-            patch -p1 < ${WORKDIR}/757-net-phy-add-phylink-pcs-support.patch
-            patch -p1 < ${WORKDIR}/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
-            patch -p1 < ${WORKDIR}/9010-iwconfig-wireless-rate-fix.patch
+            patch -p1 < ${WORKDIR}/999-2713-mt7531-gsw-internal_phy_calibration.patch
+            patch -p1 < ${WORKDIR}/999-2714-mt7531-gsw-port5_external_phy_init.patch
+            patch -p1 < ${WORKDIR}/999-2721-net-mt753x-phy-coverity-scan.patch
+            patch -p1 < ${WORKDIR}/999-1710-net-phy-add-phylink-pcs-support.patch
+            patch -p1 < ${WORKDIR}/999-1712-net-phy-add-phylink-rate-matching-support.patch
+            patch -p1 < ${WORKDIR}/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
+            patch -p1 < ${WORKDIR}/999-2725-iwconfig-wireless-rate-fix.patch
             if [ $DISTRO_secure_boot_ENABLED = 'true' ]; then
                 patch -p1 < ${WORKDIR}/0404-mtdsplit-dm-verity.patch
                 patch -p1 < ${WORKDIR}/0800-dm-verity-redo-hash-for-safexel-sha256.patch
@@ -105,13 +107,21 @@
             fi
             if [ $DISTRO_logan_ENABLED = 'true' ]; then
                 for i in ${WORKDIR}/mediatek/nf_hnat/6*.patch; do patch -p1 < $i; done
-                for i in ${WORKDIR}/mediatek/nf_hnat/10*.patch; do patch -p1 < $i; done
+                for i in ${WORKDIR}/mediatek/nf_hnat/9*.patch; do patch -p1 < $i; done
                 patch -p1 < ${WORKDIR}/004-rdkb-hnat-bind-ifname.patch
             fi
             touch patch_applied
         fi
 }
 
+do_filogic_patches_append_mt7988() {
+    if [ ! -e wed3_patch_applied ]; then
+        if [ $DISTRO_FlowBlock_ENABLED = 'true' ]; then
+                for i in ${WORKDIR}/mediatek/wed3/*.patch; do patch -p1 < $i; done
+        fi
+        touch wed3_patch_applied
+    fi
+}
 addtask filogic_patches after do_patch before do_compile
 
 KERNEL_MODULE_AUTOLOAD += "${@bb.utils.contains('DISTRO_FEATURES','logan','mtkhnat nf_flow_table_hw','',d)}"
\ No newline at end of file
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/432-missing-typedef.patch b/recipes-wifi/hostapd/files/patches-2.10.3/432-missing-typedef.patch
deleted file mode 100644
index 7a100f1..0000000
--- a/recipes-wifi/hostapd/files/patches-2.10.3/432-missing-typedef.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/src/drivers/linux_wext.h
-+++ b/src/drivers/linux_wext.h
-@@ -26,6 +26,7 @@ typedef int32_t __s32;
- typedef uint16_t __u16;
- typedef int16_t __s16;
- typedef uint8_t __u8;
-+typedef int8_t __s8;
- #ifndef __user
- #define __user
- #endif /* __user */
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
index a79555a..0892d3f 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
@@ -1,7 +1,7 @@
-From fd2df638591cc86c21153e94abe8fc00451703b8 Mon Sep 17 00:00:00 2001
+From ee34d2ccb27863f0eaa7abb0f65477ab9a0dd92f Mon Sep 17 00:00:00 2001
 From: TomLiu <tomml.liu@mediatek.com>
 Date: Tue, 9 Aug 2022 10:23:44 -0700
-Subject: [PATCH 06/28] hostapd: mtk: Add hostapd MU SET/GET control
+Subject: [PATCH 06/32] hostapd: mtk: Add hostapd MU SET/GET control
 
 ---
  hostapd/config_file.c             |   9 +++
@@ -156,14 +156,14 @@
  	{ "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL,
  	  "report a scanned DPP URI from a QR Code" },
 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 55c35c7..1cad303 100644
+index 55c35c7..afa19ec 100644
 --- a/src/ap/ap_config.c
 +++ b/src/ap/ap_config.c
 @@ -280,6 +280,7 @@ struct hostapd_config * hostapd_config_defaults(void)
  	conf->he_6ghz_max_ampdu_len_exp = 7;
  	conf->he_6ghz_rx_ant_pat = 1;
  	conf->he_6ghz_tx_ant_pat = 1;
-+	conf->mu_onoff = 13;
++	conf->mu_onoff = 15;
  #endif /* CONFIG_IEEE80211AX */
  
  	/* The third octet of the country string uses an ASCII space character
@@ -446,5 +446,5 @@
  			}
  
 -- 
-2.18.0
+2.39.0
 
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
index c53b55a..bf91686 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -1,19 +1,18 @@
-From 3237a993233da052219018eec10ca82d79225fdb Mon Sep 17 00:00:00 2001
+From 705e1a59381e7bbd92043ad4338834aad504f232 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 20 Feb 2023 16:58:20 +0800
-Subject: [PATCH 18/28] hostapd: mtk: Fix auto ht issue when switching to DFS
- channel
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- hostapd/ctrl_iface.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
+ hostapd/ctrl_iface.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
 
 diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 07de0ad..be86f6c 100644
+index 07de0ad..3c38df5 100644
 --- a/hostapd/ctrl_iface.c
 +++ b/hostapd/ctrl_iface.c
-@@ -2773,6 +2773,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2773,6 +2773,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		break;
  	}
  
@@ -21,12 +20,13 @@
 +		settings.freq_params.ht_enabled = iface->conf->ieee80211n;
 +		settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
 +		settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++		settings.freq_params.eht_enabled = iface->conf->ieee80211be;
 +	}
 +
  	if (settings.freq_params.center_freq1)
  		dfs_range += hostapd_is_dfs_overlap(
  			iface, bandwidth, settings.freq_params.center_freq1);
-@@ -2810,12 +2816,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2810,12 +2817,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		return 0;
  	}
  
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
similarity index 88%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
index 9b46d70..e4667e4 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
@@ -1,12 +1,12 @@
-From 39a0dd44653f12ce13af68de81bfae683669623a Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Thu, 11 May 2023 14:08:59 +0800
-Subject: [PATCH 101/103] hostapd: mtk: Fix CCA issue
+From c92a1e50abdad2bf3e961c9d5aa34baea81f025b Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 3 May 2023 14:55:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix CCA issue
 
-When receiving CCA related nl80211 command, hostapd used to work on
+When receiving CCA-related nl80211 commands, hostapd used to work on
 struct wpa_driver_nl80211_data, whose ctx always points to
-hostpad_iface->bss[0]. However, CCA command is sent on per-BSS based.
-This patch makes hostapd handle CCA related commands on per-BSS based.
+hostpad_iface->bss[0]. However, CCA commands are sent on a per-BSS based.
+This patch makes hostapd handle CCA-related commands on a per-BSS based.
 
 Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
 ---
@@ -93,5 +93,5 @@
  #endif /* CONFIG_IEEE80211AX */
  	default:
 -- 
-2.18.0
+2.25.1
 
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
similarity index 66%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
index 4075531..f9c4714 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
@@ -1,15 +1,14 @@
-From 097b204ffed838a4bbf7649fb23310f64ace22ad Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Thu, 11 May 2023 14:12:44 +0800
-Subject: [PATCH 102/103] hostapd: mtk: Fix unexpected AP beacon state
- transition
+From c4d3890bbf1bd8c8ac8bfaa56fd16e2391e05181 Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 3 May 2023 16:10:57 +0800
+Subject: [PATCH] hostapd: mtk: Fix unexpected AP beacon state transition
 
-When AP fails setting the beacon, it assigns bss->beacon_set to 0 no
+When AP fails to set the beacon, it assigns bss->beacon_set to 0 no
 matter what the error number is.
 However, in the case that the error number is -EBUSY, the driver might
 not free the beacon and expect a later beacon re-setting. If hostapd set
-a new beacon under this case, driver will return -EALREADY.
-This patch checks the error number after hostapd fails setting the
+a new beacon under this case, the driver will return -EALREADY.
+This patch checks the error number after hostapd fails to set the
 beacon. If the error number is -EBUSY, bss->beacon_set will not be
 assigned to 0.
 
@@ -19,7 +18,7 @@
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 8400e57..ccfc2d0 100644
+index 8400e57..5013207 100644
 --- a/src/drivers/driver_nl80211.c
 +++ b/src/drivers/driver_nl80211.c
 @@ -5126,7 +5126,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
@@ -33,5 +32,5 @@
  		bss->flink->beacon_set = 1;
  		nl80211_set_bss(bss, params->cts_protect, params->preamble,
 -- 
-2.18.0
+2.25.1
 
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch
new file mode 100644
index 0000000..1c5cacc
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch
@@ -0,0 +1,53 @@
+From 43c8934074a4f6fd1e98143b3bd011e71fe69fdb Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Fri Jun 9 09:03:05 2023 +0800
+Subject: hostapd: mtk: Add HE capabilities check
+
+Add HE capabilities check.
+Since "HE capabilities" check has been removed by driver,
+add the support for "HE capabilities" check in hostapd.
+
+---
+ src/ap/hw_features.c         | 26 ++++++++++++++++++++++++++
+ 1 files changed, 26 insertions(+)
+
+diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
+index 9967494..309f2d5 100644
+--- a/src/ap/hw_features.c
++++ b/src/ap/hw_features.c
+@@ -680,6 +680,32 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
+ #ifdef CONFIG_IEEE80211AX
+ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
+ {
++	struct hostapd_hw_modes *mode = iface->current_mode;
++	struct he_capabilities *he_cap = &mode->he_capab[IEEE80211_MODE_AP];
++	struct hostapd_config *conf = iface->conf;
++
++#define HE_CAP_CHECK(hw_cap, field, phy_idx, cfg_cap)					\
++	do {									\
++		if (cfg_cap && !(hw_cap[phy_idx] & field)) {	\
++			wpa_printf(MSG_ERROR, "Driver does not support configured" \
++				     " HE capability [%s]", #field);		\
++			return 0;						\
++		}								\
++	} while (0)
++
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_LDPC_CODING_IN_PAYLOAD,
++		     HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX,
++		     conf->he_phy_capab.he_ldpc);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_SU_BEAMFORMER_CAPAB,
++		     HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX,
++		     conf->he_phy_capab.he_su_beamformer);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_SU_BEAMFORMEE_CAPAB,
++		     HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX,
++		     conf->he_phy_capab.he_su_beamformee);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_MU_BEAMFORMER_CAPAB,
++		     HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX,
++		     conf->he_phy_capab.he_mu_beamformer);
++
+ 	return 1;
+ }
+ #endif /* CONFIG_IEEE80211AX */
+-- 
+2.39.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch
new file mode 100644
index 0000000..01a134e
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch
@@ -0,0 +1,44 @@
+From 0aaec4ebc72e40da76a279d817763f4655f45d21 Mon Sep 17 00:00:00 2001
+From: mtk23510 <rudra.shahi@mediatek.com>
+Date: Fri, 26 May 2023 14:52:35 +0800
+Subject: [PATCH] hostapd: mtk: Add support for gtk rekeying in hostapd cli
+
+Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
+---
+ hostapd/hostapd_cli.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 02f8546..d529bbc 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1256,6 +1256,15 @@ static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
+ }
+ 
+ 
++#ifdef CONFIG_TESTING_OPTIONS
++static int hostapd_cli_cmd_rekey_gtk(struct wpa_ctrl *ctrl, int argc,
++				      char *argv[])
++{
++	return wpa_ctrl_command(ctrl, "REKEY_GTK");
++}
++#endif
++
++
+ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+ 	char cmd[256];
+@@ -1761,6 +1770,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ 	  "= disable hostapd on current interface" },
+ 	{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
+ 	  "= update Beacon frame contents\n"},
++#ifdef CONFIG_TESTING_OPTIONS
++	{ "rekey_gtk", hostapd_cli_cmd_rekey_gtk, NULL,
++	  "= rekey gtk\n"},
++#endif
+ 	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
+ 	  "= drop all ERP keys"},
+ 	{ "log_level", hostapd_cli_cmd_log_level, NULL,
+-- 
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
index a71c43f..a0c06b1 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
@@ -36,7 +36,6 @@
     file://420-indicate-features.patch \
     file://430-hostapd_cli_ifdef.patch \
     file://431-wpa_cli_ifdef.patch \
-    file://432-missing-typedef.patch \
     file://450-scan_wait.patch;apply=no \
     file://460-wpa_supplicant-add-new-config-params-to-be-used-with.patch \
     file://463-add-mcast_rate-to-11s.patch \
@@ -87,8 +86,10 @@
     file://mtk-0026-hostapd-mtk-avoid-setting-beacon-after-wpa_supplican.patch \
     file://mtk-0027-hostapd-mtk-Fix-setting-wrong-seg0-index-for-5G-cent.patch \
     file://mtk-0028-hostapd-mtk-Add-muru-user-number-debug-command.patch \
+    file://mtk-0029-hostapd-mtk-Fix-CCA-issue.patch \
+    file://mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch \
+    file://mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch \
     file://mtk-0100-hostapd-mtk-update-eht-operation-element.patch \
-    file://mtk-0101-hostapd-mtk-Fix-CCA-issue.patch \
-    file://mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch \
     file://mtk-0103-hostapd-mtk-Add-BW320-channel-switch-command.patch \
+    file://mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch \
     "
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
index f89da87..d5f0dac 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -1,19 +1,18 @@
-From 0aa1200534c41279f5f05e1919040a86f003ca0a Mon Sep 17 00:00:00 2001
+From a71a78bc51b74d331aeb3f900c03480d058d5233 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 20 Feb 2023 16:58:20 +0800
-Subject: [PATCH 19/29] hostapd: mtk: Fix auto ht issue when switching to DFS
- channel
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- hostapd/ctrl_iface.c | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
 
 diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 61c9e80..06cbea1 100644
+index 61c9e80..c33b7a4 100644
 --- a/hostapd/ctrl_iface.c
 +++ b/hostapd/ctrl_iface.c
-@@ -2698,6 +2698,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		break;
  	}
  
@@ -21,13 +20,12 @@
 +		settings.freq_params.ht_enabled = iface->conf->ieee80211n;
 +		settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
 +		settings.freq_params.he_enabled = iface->conf->ieee80211ax;
-+		settings.freq_params.eht_enabled = iface->conf->ieee80211be;
 +	}
 +
  	if (settings.freq_params.center_freq1)
  		dfs_range += hostapd_is_dfs_overlap(
  			iface, bandwidth, settings.freq_params.center_freq1);
-@@ -2735,12 +2742,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		return 0;
  	}
  
diff --git a/recipes-wifi/hostapd/hostapd_2.10.3.bb b/recipes-wifi/hostapd/hostapd_2.10.3.bb
index 68cb4c2..06874d3 100644
--- a/recipes-wifi/hostapd/hostapd_2.10.3.bb
+++ b/recipes-wifi/hostapd/hostapd_2.10.3.bb
@@ -68,6 +68,7 @@
     echo "CONFIG_WEP=y" >> ${B}/.config
     echo "CONFIG_FILS=y" >> ${B}/.config
     echo "CONFIG_IEEE80211BE=y" >> ${B}/.config
+    echo "CONFIG_TESTING_OPTIONS=y" >> ${B}/.config
 }
 
 do_filogic_patches() {
diff --git a/recipes-wifi/hostapd/hostapd_2.10.bb b/recipes-wifi/hostapd/hostapd_2.10.bb
index 8f54916..e83d34e 100644
--- a/recipes-wifi/hostapd/hostapd_2.10.bb
+++ b/recipes-wifi/hostapd/hostapd_2.10.bb
@@ -67,6 +67,7 @@
     echo "CONFIG_MESH=y" >> ${B}/.config
     echo "CONFIG_WEP=y" >> ${B}/.config
     echo "CONFIG_FILS=y" >> ${B}/.config
+    echo "CONFIG_TESTING_OPTIONS=y" >> ${B}/.config
 }
 
 do_filogic_patches() {
diff --git a/recipes-wifi/libubox/libubox_git.bbappend b/recipes-wifi/libubox/libubox_git.bbappend
index 11a4d90..5bc09d3 100644
--- a/recipes-wifi/libubox/libubox_git.bbappend
+++ b/recipes-wifi/libubox/libubox_git.bbappend
@@ -1,3 +1,3 @@
 SRC_URI_remove = "file://0001-blobmsg-fix-array-out-of-bounds-GCC-10-warning.patch"
 
-SRCREV = "ea56013409d5823001b47a9bba6f74055a6d76a5"
+SRCREV = "75a3b870cace1171faf57bd55e5a9a2f1564f757"
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/050-lib80211_option.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/050-lib80211_option.patch
deleted file mode 100644
index c1b1bc7..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/050-lib80211_option.patch
+++ /dev/null
@@ -1,34 +0,0 @@
---- a/net/wireless/Kconfig
-+++ b/net/wireless/Kconfig
-@@ -188,7 +188,7 @@ config CFG80211_WEXT_EXPORT
- endif # CFG80211
- 
- config LIB80211
--	tristate
-+	tristate "lib80211"
- 	depends on m
- 	default n
- 	help
-@@ -198,19 +198,19 @@ config LIB80211
- 	  Drivers should select this themselves if needed.
- 
- config LIB80211_CRYPT_WEP
--	tristate
-+	tristate "lib80211 WEP support"
- 	depends on m
- 	select BPAUTO_CRYPTO_LIB_ARC4
- 
- config LIB80211_CRYPT_CCMP
--	tristate
-+	tristate "lib80211 CCMP support"
- 	depends on m
- 	depends on CRYPTO
- 	depends on CRYPTO_AES
- 	depends on CRYPTO_CCM
- 
- config LIB80211_CRYPT_TKIP
--	tristate
-+	tristate "lib80211 TKIP support"
- 	depends on m
- 	select BPAUTO_CRYPTO_LIB_ARC4
- 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc
index c0e4215..dbdb7b7 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc
@@ -5,7 +5,6 @@
     file://002-change_allconfig.patch \
     file://003-remove_bogus_modparams.patch \
     file://012-kernel_build_check.patch \
-    file://050-lib80211_option.patch \
     file://060-no_local_ssb_bcma.patch \
     file://070-remove-broken-wext-select.patch \
     file://080-resv_start_op.patch \
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch
index 6aec9bc..59b799b 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch
@@ -1,5 +1,6 @@
+From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001
 From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 6 Dec 2022 11:15:02 +0100
+Date: Mon, 13 Feb 2023 11:08:54 +0100
 Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh
  interfaces
 
@@ -33,7 +34,15 @@
 For forwarded packets, a new 802.11 header gets added.
 
 Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name
+[fix fortify build error]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 ---
+ .../wireless/marvell/mwifiex/11n_rxreorder.c  |   2 +-
+ include/net/cfg80211.h                        |  27 +-
+ net/mac80211/rx.c                             | 350 ++++++++++--------
+ net/wireless/util.c                           | 120 +++---
+ 4 files changed, 297 insertions(+), 202 deletions(-)
 
 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
 +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -557,7 +566,7 @@
 +		memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN);
 +		break;
 +	case MESH_FLAGS_AE_A5_A6:
-+		memcpy(&payload.eth.h_dest, mesh_addr, 2 * ETH_ALEN);
++		memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN);
 +		break;
 +	default:
 +		break;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch
new file mode 100644
index 0000000..088f468
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch
@@ -0,0 +1,372 @@
+From bd54f3c29077f23dad92ef82a78061b40be30c65 Mon Sep 17 00:00:00 2001
+From: Aloka Dixit <quic_alokad@quicinc.com>
+Date: Mon, 5 Dec 2022 16:50:37 -0800
+Subject: [PATCH] wifi: mac80211: generate EMA beacons in AP mode
+
+Add APIs to generate an array of beacons for an EMA AP (enhanced
+multiple BSSID advertisements), each including a single MBSSID element.
+EMA profile periodicity equals the count of elements.
+
+- ieee80211_beacon_get_template_ema_list() - Generate and return all
+EMA beacon templates. Drivers must call ieee80211_beacon_free_ema_list()
+to free the memory. No change in the prototype for the existing API,
+ieee80211_beacon_get_template(), which should be used for non-EMA AP.
+
+- ieee80211_beacon_get_template_ema_index() - Generate a beacon which
+includes the multiple BSSID element at the given index. Drivers can use
+this function in a loop until NULL is returned which indicates end of
+available MBSSID elements.
+
+- ieee80211_beacon_free_ema_list() - free the memory allocated for the
+list of EMA beacon templates.
+
+Modify existing functions ieee80211_beacon_get_ap(),
+ieee80211_get_mbssid_beacon_len() and ieee80211_beacon_add_mbssid()
+to accept a new parameter for EMA index.
+
+Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
+Co-developed-by: John Crispin <john@phrozen.org>
+Signed-off-by: John Crispin <john@phrozen.org>
+Link: https://lore.kernel.org/r/20221206005040.3177-2-quic_alokad@quicinc.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+ include/net/mac80211.h     |  68 +++++++++++++++++++
+ net/mac80211/cfg.c         |  11 +--
+ net/mac80211/ieee80211_i.h |  10 ++-
+ net/mac80211/tx.c          | 134 ++++++++++++++++++++++++++++++++++---
+ 4 files changed, 205 insertions(+), 18 deletions(-)
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5252,6 +5252,74 @@ ieee80211_beacon_get_template(struct iee
+ 			      unsigned int link_id);
+ 
+ /**
++ * ieee80211_beacon_get_template_ema_index - EMA beacon template generation
++ * @hw: pointer obtained from ieee80211_alloc_hw().
++ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
++ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
++ *	receive the offsets that may be updated by the driver.
++ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP).
++ * @ema_index: index of the beacon in the EMA set.
++ *
++ * This function follows the same rules as ieee80211_beacon_get_template()
++ * but returns a beacon template which includes multiple BSSID element at the
++ * requested index.
++ *
++ * Return: The beacon template. %NULL indicates the end of EMA templates.
++ */
++struct sk_buff *
++ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
++					struct ieee80211_vif *vif,
++					struct ieee80211_mutable_offsets *offs,
++					unsigned int link_id, u8 ema_index);
++
++/**
++ * struct ieee80211_ema_beacons - List of EMA beacons
++ * @cnt: count of EMA beacons.
++ *
++ * @bcn: array of EMA beacons.
++ * @bcn.skb: the skb containing this specific beacon
++ * @bcn.offs: &struct ieee80211_mutable_offsets pointer to struct that will
++ *	receive the offsets that may be updated by the driver.
++ */
++struct ieee80211_ema_beacons {
++	u8 cnt;
++	struct {
++		struct sk_buff *skb;
++		struct ieee80211_mutable_offsets offs;
++	} bcn[];
++};
++
++/**
++ * ieee80211_beacon_get_template_ema_list - EMA beacon template generation
++ * @hw: pointer obtained from ieee80211_alloc_hw().
++ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
++ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP)
++ *
++ * This function follows the same rules as ieee80211_beacon_get_template()
++ * but allocates and returns a pointer to list of all beacon templates required
++ * to cover all profiles in the multiple BSSID set. Each template includes only
++ * one multiple BSSID element.
++ *
++ * Driver must call ieee80211_beacon_free_ema_list() to free the memory.
++ *
++ * Return: EMA beacon templates of type struct ieee80211_ema_beacons *.
++ *	%NULL on error.
++ */
++struct ieee80211_ema_beacons *
++ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
++				       struct ieee80211_vif *vif,
++				       unsigned int link_id);
++
++/**
++ * ieee80211_beacon_free_ema_list - free an EMA beacon template list
++ * @ema_beacons: list of EMA beacons of type &struct ieee80211_ema_beacons pointers.
++ *
++ * This function will free a list previously acquired by calling
++ * ieee80211_beacon_get_template_ema_list()
++ */
++void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons);
++
++/**
+  * ieee80211_beacon_get_tim - beacon generation function
+  * @hw: pointer obtained from ieee80211_alloc_hw().
+  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1122,11 +1122,11 @@ static int ieee80211_assign_beacon(struc
+ 	if (params->mbssid_ies) {
+ 		mbssid = params->mbssid_ies;
+ 		size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
+-		size += ieee80211_get_mbssid_beacon_len(mbssid);
++		size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
+ 	} else if (old && old->mbssid_ies) {
+ 		mbssid = old->mbssid_ies;
+ 		size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
+-		size += ieee80211_get_mbssid_beacon_len(mbssid);
++		size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
+ 	}
+ 
+ 	new = kzalloc(size, GFP_KERNEL);
+@@ -3384,8 +3384,11 @@ cfg80211_beacon_dup(struct cfg80211_beac
+ 
+ 	len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
+ 	      beacon->proberesp_ies_len + beacon->assocresp_ies_len +
+-	      beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
+-	      ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
++	      beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
++
++	if (beacon->mbssid_ies)
++		len += ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
++						       beacon->mbssid_ies->cnt);
+ 
+ 	new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
+ 	if (!new_beacon)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1182,13 +1182,17 @@ ieee80211_vif_get_shift(struct ieee80211
+ }
+ 
+ static inline int
+-ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems)
++ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, u8 i)
+ {
+-	int i, len = 0;
++	int len = 0;
+ 
+-	if (!elems)
++	if (!elems || !elems->cnt || i > elems->cnt)
+ 		return 0;
+ 
++	if (i < elems->cnt)
++		return elems->elem[i].len;
++
++	/* i == elems->cnt, calculate total length of all MBSSID elements */
+ 	for (i = 0; i < elems->cnt; i++)
+ 		len += elems->elem[i].len;
+ 
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -5205,13 +5205,20 @@ ieee80211_beacon_get_finish(struct ieee8
+ }
+ 
+ static void
+-ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon)
++ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
++			    u8 i)
+ {
+-	int i;
++	if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt ||
++	    i > beacon->mbssid_ies->cnt)
++		return;
+ 
+-	if (!beacon->mbssid_ies)
++	if (i < beacon->mbssid_ies->cnt) {
++		skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
++			     beacon->mbssid_ies->elem[i].len);
+ 		return;
++	}
+ 
++	/* i == beacon->mbssid_ies->cnt, include all MBSSID elements */
+ 	for (i = 0; i < beacon->mbssid_ies->cnt; i++)
+ 		skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
+ 			     beacon->mbssid_ies->elem[i].len);
+@@ -5224,7 +5231,8 @@ ieee80211_beacon_get_ap(struct ieee80211
+ 			struct ieee80211_mutable_offsets *offs,
+ 			bool is_template,
+ 			struct beacon_data *beacon,
+-			struct ieee80211_chanctx_conf *chanctx_conf)
++			struct ieee80211_chanctx_conf *chanctx_conf,
++			u8 ema_index)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+ 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+@@ -5243,7 +5251,9 @@ ieee80211_beacon_get_ap(struct ieee80211
+ 	/* headroom, head length,
+ 	 * tail length, maximum TIM length and multiple BSSID length
+ 	 */
+-	mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
++	mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
++						     ema_index);
++
+ 	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
+ 			    beacon->tail_len + 256 +
+ 			    local->hw.extra_beacon_tailroom + mbssid_len);
+@@ -5261,7 +5271,7 @@ ieee80211_beacon_get_ap(struct ieee80211
+ 		offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
+ 
+ 		if (mbssid_len) {
+-			ieee80211_beacon_add_mbssid(skb, beacon);
++			ieee80211_beacon_add_mbssid(skb, beacon, ema_index);
+ 			offs->mbssid_off = skb->len - mbssid_len;
+ 		}
+ 
+@@ -5280,12 +5290,51 @@ ieee80211_beacon_get_ap(struct ieee80211
+ 	return skb;
+ }
+ 
++static struct ieee80211_ema_beacons *
++ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
++				 struct ieee80211_vif *vif,
++				 struct ieee80211_link_data *link,
++				 struct ieee80211_mutable_offsets *offs,
++				 bool is_template, struct beacon_data *beacon,
++				 struct ieee80211_chanctx_conf *chanctx_conf)
++{
++	struct ieee80211_ema_beacons *ema = NULL;
++
++	if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt)
++		return NULL;
++
++	ema = kzalloc(struct_size(ema, bcn, beacon->mbssid_ies->cnt),
++		      GFP_ATOMIC);
++	if (!ema)
++		return NULL;
++
++	for (ema->cnt = 0; ema->cnt < beacon->mbssid_ies->cnt; ema->cnt++) {
++		ema->bcn[ema->cnt].skb =
++			ieee80211_beacon_get_ap(hw, vif, link,
++						&ema->bcn[ema->cnt].offs,
++						is_template, beacon,
++						chanctx_conf, ema->cnt);
++		if (!ema->bcn[ema->cnt].skb)
++			break;
++	}
++
++	if (ema->cnt == beacon->mbssid_ies->cnt)
++		return ema;
++
++	ieee80211_beacon_free_ema_list(ema);
++	return NULL;
++}
++
++#define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS -1
++
+ static struct sk_buff *
+ __ieee80211_beacon_get(struct ieee80211_hw *hw,
+ 		       struct ieee80211_vif *vif,
+ 		       struct ieee80211_mutable_offsets *offs,
+ 		       bool is_template,
+-		       unsigned int link_id)
++		       unsigned int link_id,
++		       int ema_index,
++		       struct ieee80211_ema_beacons **ema_beacons)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+ 	struct beacon_data *beacon = NULL;
+@@ -5314,8 +5363,29 @@ __ieee80211_beacon_get(struct ieee80211_
+ 		if (!beacon)
+ 			goto out;
+ 
+-		skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template,
+-					      beacon, chanctx_conf);
++		if (ema_beacons) {
++			*ema_beacons =
++				ieee80211_beacon_get_ap_ema_list(hw, vif, link,
++								 offs,
++								 is_template,
++								 beacon,
++								 chanctx_conf);
++		} else {
++			if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
++				if (ema_index >= beacon->mbssid_ies->cnt)
++					goto out; /* End of MBSSID elements */
++
++				if (ema_index <= IEEE80211_INCLUDE_ALL_MBSSID_ELEMS)
++					ema_index = beacon->mbssid_ies->cnt;
++			} else {
++				ema_index = 0;
++			}
++
++			skb = ieee80211_beacon_get_ap(hw, vif, link, offs,
++						      is_template, beacon,
++						      chanctx_conf,
++						      ema_index);
++		}
+ 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ 		struct ieee80211_hdr *hdr;
+@@ -5403,10 +5473,50 @@ ieee80211_beacon_get_template(struct iee
+ 			      struct ieee80211_mutable_offsets *offs,
+ 			      unsigned int link_id)
+ {
+-	return __ieee80211_beacon_get(hw, vif, offs, true, link_id);
++	return __ieee80211_beacon_get(hw, vif, offs, true, link_id,
++				      IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, NULL);
+ }
+ EXPORT_SYMBOL(ieee80211_beacon_get_template);
+ 
++struct sk_buff *
++ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
++					struct ieee80211_vif *vif,
++					struct ieee80211_mutable_offsets *offs,
++					unsigned int link_id, u8 ema_index)
++{
++	return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index,
++				      NULL);
++}
++EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index);
++
++void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons)
++{
++	u8 i;
++
++	if (!ema_beacons)
++		return;
++
++	for (i = 0; i < ema_beacons->cnt; i++)
++		kfree_skb(ema_beacons->bcn[i].skb);
++
++	kfree(ema_beacons);
++}
++EXPORT_SYMBOL(ieee80211_beacon_free_ema_list);
++
++struct ieee80211_ema_beacons *
++ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
++				       struct ieee80211_vif *vif,
++				       unsigned int link_id)
++{
++	struct ieee80211_ema_beacons *ema_beacons = NULL;
++
++	WARN_ON(__ieee80211_beacon_get(hw, vif, NULL, false, link_id, 0,
++				       &ema_beacons));
++
++	return ema_beacons;
++}
++EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list);
++
+ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
+ 					 struct ieee80211_vif *vif,
+ 					 u16 *tim_offset, u16 *tim_length,
+@@ -5414,7 +5524,9 @@ struct sk_buff *ieee80211_beacon_get_tim
+ {
+ 	struct ieee80211_mutable_offsets offs = {};
+ 	struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false,
+-						     link_id);
++						     link_id,
++						     IEEE80211_INCLUDE_ALL_MBSSID_ELEMS,
++						     NULL);
+ 	struct sk_buff *copy;
+ 	int shift;
+ 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
index b1e84e2..4a3984f 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
@@ -77,7 +77,7 @@
  static void ieee80211_rfkill_poll(struct wiphy *wiphy)
  {
  	struct ieee80211_local *local = wiphy_priv(wiphy);
-@@ -4953,6 +4966,7 @@ const struct cfg80211_ops mac80211_confi
+@@ -4956,6 +4969,7 @@ const struct cfg80211_ops mac80211_confi
  	.set_wiphy_params = ieee80211_set_wiphy_params,
  	.set_tx_power = ieee80211_set_tx_power,
  	.get_tx_power = ieee80211_get_tx_power,
@@ -87,7 +87,7 @@
  	CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -1538,6 +1538,7 @@ struct ieee80211_local {
+@@ -1542,6 +1542,7 @@ struct ieee80211_local {
  	int dynamic_ps_forced_timeout;
  
  	int user_power_level; /* in dBm, for all interfaces */
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch
new file mode 100644
index 0000000..c0f4c01
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch
@@ -0,0 +1,59 @@
+From 7097dfcbf442fde86cfb34f8e91fb5c0e6546630 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 29 Mar 2022 16:06:30 +0800
+Subject: [PATCH] cfg80211: mtk: extend CAC time for weather radar channels
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ include/net/cfg80211.h | 1 +
+ net/wireless/chan.c    | 6 ++++++
+ net/wireless/nl80211.c | 3 +++
+ 3 files changed, 10 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 8d72357..a6bf255 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -149,6 +149,7 @@ enum ieee80211_channel_flags {
+ 	(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+ 
+ #define IEEE80211_DFS_MIN_CAC_TIME_MS		60000
++#define IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS	600000
+ #define IEEE80211_DFS_MIN_NOP_TIME_MS		(30 * 60 * 1000)
+ 
+ /**
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index d5ed976..fef0ba5 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -931,6 +931,12 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+ 		if (!(c->flags & IEEE80211_CHAN_RADAR))
+ 			continue;
+ 
++		/* weather radar in ETSI */
++		if (reg_get_dfs_region(wiphy) == NL80211_DFS_ETSI &&
++		    freq >= MHZ_TO_KHZ(5590) && freq <= MHZ_TO_KHZ(5650) &&
++		    dfs_cac_ms < IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS)
++			dfs_cac_ms = IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS;
++
+ 		if (c->dfs_cac_ms > dfs_cac_ms)
+ 			dfs_cac_ms = c->dfs_cac_ms;
+ 	}
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index f3b2fc4..215a603 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -9817,6 +9817,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ 	if (WARN_ON(!cac_time_ms))
+ 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ 
++	pr_info("%s: region = %u, center freq1 = %u, center freq2 = %u, cac time ms = %u\n",
++		__func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
++
+ 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
+ 	if (!err) {
+ 		wdev->links[0].ap.chandef = chandef;
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch
deleted file mode 100644
index cfd0e09..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From dacd08119ef3964c826d1949b35c5b926b40eb2b Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Tue, 29 Mar 2022 16:06:30 +0800
-Subject: [PATCH 02/14] nl80211: mtk: extend CAC time for weather radar
- channels
-
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- net/wireless/nl80211.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index f3b2fc4..0430bbe 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -9817,6 +9817,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
- 	if (WARN_ON(!cac_time_ms))
- 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
- 
-+	if ((dfs_region == NL80211_DFS_ETSI) &&
-+	    (((chandef.width == NL80211_CHAN_WIDTH_160) &&
-+	     (chandef.center_freq2 >= 5580 && chandef.center_freq2 <= 5640)) ||
-+	    (chandef.center_freq1 >= 5580 && chandef.center_freq1 <= 5640)))
-+		cac_time_ms = 600000;
-+	pr_info("%s: region = %u, cetner freq1 = %u, center freq2 = %u, cac time ms = %u\n", __func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
-+
- 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
- 	if (!err) {
- 		wdev->links[0].ap.chandef = chandef;
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-support-configurable-addba-resp-time.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-support-configurable-addba-resp-time.patch
new file mode 100644
index 0000000..759d36b
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-support-configurable-addba-resp-time.patch
@@ -0,0 +1,42 @@
+From 0236a4a01f3f3ed932ab326de0deef6911519dab Mon Sep 17 00:00:00 2001
+From: Lian Chen <lian.chen@mediatek.com>
+Date: Wed, 7 Jun 2023 15:30:34 +0800
+Subject: [PATCH] support configurable addba resp time.
+
+---
+ net/mac80211/agg-tx.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index 6992c1f..ad0c0d6 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -16,10 +16,16 @@
+ #include <linux/slab.h>
+ #include <linux/export.h>
+ #include <net/mac80211.h>
++#include <linux/moduleparam.h>
+ #include "ieee80211_i.h"
+ #include "driver-ops.h"
+ #include "wme.h"
+ 
++static int addba_resp_wait_count = 2;
++module_param(addba_resp_wait_count, int, 0644);
++MODULE_PARM_DESC(addba_resp_wait_count,
++		 "Number of ADDBA_RESP_INTERVAL to wait for addba response");
++
+ /**
+  * DOC: TX A-MPDU aggregation
+  *
+@@ -460,7 +466,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
+ 	u16 buf_size;
+ 
+ 	/* activate the timer for the recipient's addBA response */
+-	mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
++	mod_timer(&tid_tx->addba_resp_timer, jiffies + addba_resp_wait_count * ADDBA_RESP_INTERVAL);
+ 	ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
+ 	       sta->sta.addr, tid);
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
new file mode 100644
index 0000000..f14111c
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
@@ -0,0 +1,180 @@
+From e545285e24de95d0d620bb7e9c97abba39e363b9 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:25:24 +0800
+Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ include/net/cfg80211.h       | 14 +++++++++
+ include/uapi/linux/nl80211.h |  6 ++++
+ net/mac80211/mlme.c          | 12 ++++++++
+ net/wireless/chan.c          | 60 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 92 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 84564bd..06d1567 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -8180,6 +8180,20 @@ void cfg80211_cac_event(struct net_device *netdev,
+ 			const struct cfg80211_chan_def *chandef,
+ 			enum nl80211_radar_event event, gfp_t gfp);
+ 
++/**
++ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
++ *				   association, and disassociation
++ * @wdev: the wireless device
++ * @bss_chandef: the current BSS channel definition
++ * @csa_chandef: the CSA channel definition
++ * @associated: whether STA is during association or disassociation process
++ *
++ */
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++				   const struct cfg80211_chan_def *bss_chandef,
++				   const struct cfg80211_chan_def *csa_chandef,
++				   bool associated);
++
+ /**
+  * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
+  * @wiphy: the wiphy
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index bd26a06..e453d64 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -6565,6 +6565,10 @@ enum nl80211_smps_mode {
+  *	applicable for ETSI dfs domain where pre-CAC is valid for ever.
+  * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+  *	should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ *	when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ *	when STA is disconnected or leaving the channel
+  */
+ enum nl80211_radar_event {
+ 	NL80211_RADAR_DETECTED,
+@@ -6573,6 +6577,8 @@ enum nl80211_radar_event {
+ 	NL80211_RADAR_NOP_FINISHED,
+ 	NL80211_RADAR_PRE_CAC_EXPIRED,
+ 	NL80211_RADAR_CAC_STARTED,
++	NL80211_RADAR_STA_CAC_SKIPPED,
++	NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+ 
+ /**
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 72d153f..5a3dd31 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1987,6 +1987,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
+ 					  IEEE80211_QUEUE_STOP_REASON_CSA);
+ 	mutex_unlock(&local->mtx);
+ 
++	cfg80211_sta_update_dfs_state(&sdata->wdev,
++				      &sdata->vif.bss_conf.chandef,
++				      &link->csa_chandef,
++				      sdata->vif.cfg.assoc);
++
+ 	cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
+ 					  csa_ie.count, csa_ie.mode, 0);
+ 
+@@ -3072,6 +3077,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ 	       sizeof(sdata->vif.bss_conf.tx_pwr_env));
+ 
+ 	ieee80211_vif_set_links(sdata, 0);
++
++	cfg80211_sta_update_dfs_state(&sdata->wdev,
++				      &sdata->vif.bss_conf.chandef,
++				      NULL, sdata->vif.cfg.assoc);
+ }
+ 
+ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
+@@ -5276,6 +5285,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ 		event.u.mlme.status = MLME_SUCCESS;
+ 		drv_event_callback(sdata->local, sdata, &event);
+ 		sdata_info(sdata, "associated\n");
++		cfg80211_sta_update_dfs_state(&sdata->wdev,
++					      &sdata->vif.bss_conf.chandef,
++					      NULL, sdata->vif.cfg.assoc);
+ 
+ 		info.success = 1;
+ 	}
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index fef0ba5..13276bc 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -14,6 +14,7 @@
+ #include <net/cfg80211.h>
+ #include "core.h"
+ #include "rdev-ops.h"
++#include "nl80211.h"
+ 
+ static bool cfg80211_valid_60g_freq(u32 freq)
+ {
+@@ -1436,6 +1437,65 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
+ }
+ EXPORT_SYMBOL(cfg80211_any_usable_channels);
+ 
++static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
++				      const struct cfg80211_chan_def *chandef,
++				      enum nl80211_radar_event event)
++{
++	struct wireless_dev *wdev;
++
++	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
++		if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
++			nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
++					     event, wdev->netdev, GFP_KERNEL);
++			return;
++		}
++	}
++}
++
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++				   const struct cfg80211_chan_def *bss_chandef,
++				   const struct cfg80211_chan_def *csa_chandef,
++				   bool associated)
++{
++	bool csa_active = !!csa_chandef;
++	enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
++	enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
++
++	if (!bss_chandef)
++		return;
++
++	/* assume csa channel is cac completed */
++	if (csa_active &&
++	    (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
++	    cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
++		cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
++		cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
++					  NL80211_RADAR_STA_CAC_SKIPPED);
++		netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
++	}
++
++	/* avoid updating the dfs state during nop */
++	if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
++	    !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
++		return;
++
++	if (associated && !csa_active) {
++		dfs_state = NL80211_DFS_AVAILABLE;
++		event = NL80211_RADAR_STA_CAC_SKIPPED;
++	}
++
++	cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
++	cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
++
++	if (csa_active)
++		netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
++	else
++		netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
++			    (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
++			    associated ? "association" : "disassociation");
++}
++EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
++
+ struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
+ 				       unsigned int link_id)
+ {
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..cdc6290
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,28 @@
+From 4c78e6469da8de9c4584d029231938063545b031 Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 17 Mar 2023 17:36:01 +0800
+Subject: [PATCH] nl80211: mtk: Mark DFS channel as available for CSA.
+
+---
+ net/wireless/nl80211.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index af43c22..53f32c6 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -10079,6 +10079,11 @@ skip_beacons:
+ 	if (err)
+ 		goto free;
+ 
++	/* Use RADAR_BACKGROUND attribute here for skipping CAC */
++	if (info->attrs[NL80211_ATTR_RADAR_BACKGROUND]) {
++		cfg80211_set_dfs_state(&rdev->wiphy, &params.chandef, NL80211_DFS_AVAILABLE);
++	}
++
+ 	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
+ 					   wdev->iftype)) {
+ 		err = -EINVAL;
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1000-mac80211-mtk-add-EHT-BA1024-support.patch
similarity index 92%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1000-mac80211-mtk-add-EHT-BA1024-support.patch
index 5493895..fe7b1af 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1000-mac80211-mtk-add-EHT-BA1024-support.patch
@@ -1,7 +1,7 @@
-From 21b39d41faf3a67127778d85a79029002ed65291 Mon Sep 17 00:00:00 2001
+From 5a82834ed7eb4cbf0f4f5abc8665eeef023b67ff Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Sun, 25 Dec 2022 22:43:46 +0800
-Subject: [PATCH 100/102] mac80211: mtk: add EHT BA1024 support
+Subject: [PATCH 1000/1003] mac80211: mtk: add EHT BA1024 support
 
 ---
  include/linux/ieee80211.h |  2 ++
@@ -9,10 +9,10 @@
  2 files changed, 45 insertions(+), 2 deletions(-)
 
 diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
-index 6f70394..27321f2 100644
+index 00d381e..0781b76 100644
 --- a/include/linux/ieee80211.h
 +++ b/include/linux/ieee80211.h
-@@ -1270,6 +1270,8 @@ struct ieee80211_mgmt {
+@@ -1256,6 +1256,8 @@ struct ieee80211_mgmt {
  					__le16 status;
  					__le16 capab;
  					__le16 timeout;
@@ -22,7 +22,7 @@
  				struct{
  					u8 action_code;
 diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 56cd1fc..8daf292 100644
+index 752ad09..7f0e72a 100644
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
 @@ -66,10 +66,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -73,7 +73,7 @@
  	} else {
  		/*
  		 * We really should use what the driver told us it will
-@@ -978,13 +997,35 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
+@@ -980,13 +999,35 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
  {
  	struct tid_ampdu_tx *tid_tx;
  	struct ieee80211_txq *txq;
@@ -110,5 +110,5 @@
  
  	txq = sta->sta.txq[tid];
 -- 
-2.18.0
+2.39.2
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1001-mac80211-mtk-add-rate-duration-for-EHT-rate.patch
similarity index 98%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1001-mac80211-mtk-add-rate-duration-for-EHT-rate.patch
index 27ed002..f20cb61 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1001-mac80211-mtk-add-rate-duration-for-EHT-rate.patch
@@ -1,7 +1,7 @@
-From a1d426d8bb909612b66c31d450fd717177862d2f Mon Sep 17 00:00:00 2001
+From 857debd24af093da4e85f148767fd16fb9eaf975 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Sun, 25 Dec 2022 22:43:46 +0800
-Subject: [PATCH 101/102] mac80211: mtk: add rate duration for EHT rate.
+Subject: [PATCH 1001/1003] mac80211: mtk: add rate duration for EHT rate.
 
 ---
  net/mac80211/airtime.c | 349 ++++++++++++++++++++++++++++++++++++++++-
@@ -436,5 +436,5 @@
  	if (stat->encoding != RX_ENC_LEGACY)
  		return true;
 -- 
-2.18.0
+2.39.2
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0103-mac80211-mtk-add-send-bar-on-addbarsp_handle.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1002-mac80211-mtk-add-send-bar-action-when-recieve-addba-.patch
similarity index 68%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0103-mac80211-mtk-add-send-bar-on-addbarsp_handle.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1002-mac80211-mtk-add-send-bar-action-when-recieve-addba-.patch
index 054d623..099071c 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0103-mac80211-mtk-add-send-bar-on-addbarsp_handle.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1002-mac80211-mtk-add-send-bar-action-when-recieve-addba-.patch
@@ -1,21 +1,19 @@
-From 64b7f68018adbbbe33c6edb602c05dc19f8c5ea8 Mon Sep 17 00:00:00 2001
+From a9b8e0e62b19fbd7c1dd865330ceb5a943e5cbb2 Mon Sep 17 00:00:00 2001
 From: ye he <ye.he@mediatek.com>
 Date: Wed, 22 Feb 2023 16:09:32 +0800
-Subject: [PATCH] add send bar action when recieve addba rsp
+Subject: [PATCH 1002/1003] mac80211: mtk: add send bar action when recieve
+ addba rsp
 
 Signed-off-by: ye he <ye.he@mediatek.com>
 ---
  net/mac80211/agg-tx.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
- mode change 100755 => 100644 net/mac80211/agg-tx.c
 
 diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-old mode 100755
-new mode 100644
-index 7f750c1..4292258
+index 7f0e72a..3ce2226 100644
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
-@@ -1060,7 +1060,8 @@ next:
+@@ -1080,7 +1080,8 @@ next:
  
  		tid_tx->buf_size = buf_size;
  		tid_tx->amsdu = amsdu;
@@ -26,5 +24,5 @@
  			ieee80211_agg_tx_operational(local, sta, tid);
  
 -- 
-2.18.0
+2.39.2
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1003-mac80211-mtk-inrease-beacon-loss-count.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1003-mac80211-mtk-inrease-beacon-loss-count.patch
new file mode 100644
index 0000000..1def860
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1003-mac80211-mtk-inrease-beacon-loss-count.patch
@@ -0,0 +1,33 @@
+From 8175f5cdf45728cdfcf34893696f994c6f1e6cc1 Mon Sep 17 00:00:00 2001
+From: Amit Khatri <amit.khatri@mediatek.com>
+Date: Thu, 6 Apr 2023 21:37:33 +0800
+Subject: [PATCH 1003/1003] mac80211: mtk: inrease beacon loss count
+
+as per eagle code beacone loss time out is
+4 seconds.
+in 2G connection getting beacon loss logs in routed client
+scenario.
+
+so increasing beacon loss count from 7 to 20
+
+Signed-off-by: Amit Khatri <amit.khatri@mediatek.com>
+---
+ net/mac80211/mlme.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 72d153f..458609c 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -61,7 +61,7 @@ MODULE_PARM_DESC(max_probe_tries,
+  * probe on beacon miss before declaring the connection lost
+  * default to what we want.
+  */
+-static int beacon_loss_count = 7;
++static int beacon_loss_count = 20;
+ module_param(beacon_loss_count, int, 0644);
+ MODULE_PARM_DESC(beacon_loss_count,
+ 		 "Number of beacon intervals before we decide beacon was lost.");
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1004-mac80211-mtk-add-disabling-cca-when-stopping-AP.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1004-mac80211-mtk-add-disabling-cca-when-stopping-AP.patch
new file mode 100644
index 0000000..c8fc398
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-1004-mac80211-mtk-add-disabling-cca-when-stopping-AP.patch
@@ -0,0 +1,24 @@
+From 79837bcb22a80a4c95cbba77b23f16352d4e791d Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Mon, 24 Apr 2023 09:59:24 +0800
+Subject: [PATCH] mac80211: mtk: add disabling cca when stopping AP.
+
+---
+ net/mac80211/cfg.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 343ce2b..611c29e 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1540,6 +1540,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
+ 	/* abort any running channel switch */
+ 	mutex_lock(&local->mtx);
+ 	link_conf->csa_active = false;
++	link_conf->color_change_active = false;
+ 	if (link->csa_block_tx) {
+ 		ieee80211_wake_vif_queues(local, sdata,
+ 					  IEEE80211_QUEUE_STOP_REASON_CSA);
+-- 
+2.25.1
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
index 9da26b5..cea85f7 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
@@ -36,6 +36,7 @@
     file://333-wifi-mac80211-add-flush_sta-method.patch \
     file://334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch \
     file://335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch \
+    file://336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch \
     file://400-allow-ibss-mixed.patch \
     file://500-mac80211_configure_antenna_gain.patch \
     file://782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch \
@@ -49,7 +50,7 @@
     file://bp-0008-wifi-mac80211-configure-puncturing-bitmap.patch \
     file://bp-0009-wifi-mac80211-add-EHT-MU-MIMO-related-flags-in-ieee8.patch \
     file://mtk-0001-mac80211-mtk-do-not-setup-twt-when-twt-responder-is-.patch \
-    file://mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch \
+    file://mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch \
     file://mtk-0003-mac80211-mtk-it-s-invalid-case-when-frag_threshold-i.patch \
     file://mtk-0004-mac80211-mtk-airtime_flags-depends-on-NL80211_EXT_FE.patch \
     file://mtk-0005-mac80211-mtk-add-support-for-runtime-set-inband-disc.patch \
@@ -62,7 +63,12 @@
     file://mtk-0012-mac80211-mtk-track-obss-color-bitmap.patch \
     file://mtk-0013-mac80211-mtk-ageout-color-bitmap.patch \
     file://mtk-0014-mac80211-mtk-update-max_bssid_indicator-based-on-rea.patch \
-    file://mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch \
-    file://mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch \
-    file://mtk-0103-mac80211-mtk-add-send-bar-on-addbarsp_handle.patch \
+    file://mtk-0015-mac80211-support-configurable-addba-resp-time.patch \
+    file://mtk-0016-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch \
+    file://mtk-0017-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+    file://mtk-1000-mac80211-mtk-add-EHT-BA1024-support.patch \
+    file://mtk-1001-mac80211-mtk-add-rate-duration-for-EHT-rate.patch \
+    file://mtk-1002-mac80211-mtk-add-send-bar-action-when-recieve-addba-.patch \
+    file://mtk-1003-mac80211-mtk-inrease-beacon-loss-count.patch \
+    file://mtk-1004-mac80211-mtk-add-disabling-cca-when-stopping-AP.patch \
     "
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch
new file mode 100644
index 0000000..f5b52c4
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch
@@ -0,0 +1,59 @@
+From b6a99ac9380eb282d251a349709483579186bc51 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 29 Mar 2022 16:06:30 +0800
+Subject: [PATCH] cfg80211: mtk: extend CAC time for weather radar channels
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ include/net/cfg80211.h | 1 +
+ net/wireless/chan.c    | 6 ++++++
+ net/wireless/nl80211.c | 3 +++
+ 3 files changed, 10 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 8e05f55..585d934 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -142,6 +142,7 @@ enum ieee80211_channel_flags {
+ 	(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+ 
+ #define IEEE80211_DFS_MIN_CAC_TIME_MS		60000
++#define IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS	600000
+ #define IEEE80211_DFS_MIN_NOP_TIME_MS		(30 * 60 * 1000)
+ 
+ /**
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index 5f50ac4..6b42040 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -843,6 +843,12 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+ 		if (!(c->flags & IEEE80211_CHAN_RADAR))
+ 			continue;
+ 
++		/* weather radar in ETSI */
++		if (reg_get_dfs_region(wiphy) == NL80211_DFS_ETSI &&
++		    freq >= MHZ_TO_KHZ(5590) && freq <= MHZ_TO_KHZ(5650) &&
++		    dfs_cac_ms < IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS)
++			dfs_cac_ms = IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS;
++
+ 		if (c->dfs_cac_ms > dfs_cac_ms)
+ 			dfs_cac_ms = c->dfs_cac_ms;
+ 	}
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index bc6b5ac..bc07fe8 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -9354,6 +9354,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ 	if (WARN_ON(!cac_time_ms))
+ 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ 
++	pr_info("%s: region = %u, center freq1 = %u, center freq2 = %u, cac time ms = %u\n",
++		__func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
++
+ 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
+ 	if (!err) {
+ 		wdev->chandef = chandef;
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch
deleted file mode 100644
index e281cdd..0000000
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 90338d1909357f0fac0ec1f0ead5f4a9b47524b9 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Tue, 29 Mar 2022 16:06:30 +0800
-Subject: [PATCH 02/17] nl80211: mtk: extend CAC time for weather radar
- channels
-
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
----
- net/wireless/nl80211.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index bc6b5ac..3c6c1df 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -9354,6 +9354,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
- 	if (WARN_ON(!cac_time_ms))
- 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
- 
-+	if ((dfs_region == NL80211_DFS_ETSI) &&
-+	    (((chandef.width == NL80211_CHAN_WIDTH_160) &&
-+	     (chandef.center_freq2 >= 5580 && chandef.center_freq2 <= 5640)) ||
-+	    (chandef.center_freq1 >= 5580 && chandef.center_freq1 <= 5640)))
-+		cac_time_ms = 600000;
-+	pr_info("%s: region = %u, cetner freq1 = %u, center freq2 = %u, cac time ms = %u\n", __func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
-+
- 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
- 	if (!err) {
- 		wdev->chandef = chandef;
--- 
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0018-mac80211-support-configurable-addba-resp-time.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0018-mac80211-support-configurable-addba-resp-time.patch
new file mode 100644
index 0000000..759d36b
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0018-mac80211-support-configurable-addba-resp-time.patch
@@ -0,0 +1,42 @@
+From 0236a4a01f3f3ed932ab326de0deef6911519dab Mon Sep 17 00:00:00 2001
+From: Lian Chen <lian.chen@mediatek.com>
+Date: Wed, 7 Jun 2023 15:30:34 +0800
+Subject: [PATCH] support configurable addba resp time.
+
+---
+ net/mac80211/agg-tx.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index 6992c1f..ad0c0d6 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -16,10 +16,16 @@
+ #include <linux/slab.h>
+ #include <linux/export.h>
+ #include <net/mac80211.h>
++#include <linux/moduleparam.h>
+ #include "ieee80211_i.h"
+ #include "driver-ops.h"
+ #include "wme.h"
+ 
++static int addba_resp_wait_count = 2;
++module_param(addba_resp_wait_count, int, 0644);
++MODULE_PARM_DESC(addba_resp_wait_count,
++		 "Number of ADDBA_RESP_INTERVAL to wait for addba response");
++
+ /**
+  * DOC: TX A-MPDU aggregation
+  *
+@@ -460,7 +466,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
+ 	u16 buf_size;
+ 
+ 	/* activate the timer for the recipient's addBA response */
+-	mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
++	mod_timer(&tid_tx->addba_resp_timer, jiffies + addba_resp_wait_count * ADDBA_RESP_INTERVAL);
+ 	ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
+ 	       sta->sta.addr, tid);
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
index 3a7ae6b..fd7f151 100644
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
@@ -56,7 +56,7 @@
     file://783-sync-nl80211.patch \
     file://800-mac80211-mask-nested-A-MSDU-support-for-mesh.patch \
     file://mtk-0001-mac80211-mtk-do-not-setup-twt-when-twt-responder-is-.patch \
-    file://mtk-0002-nl80211-mtk-extend-CAC-time-for-weather-radar-channe.patch \
+    file://mtk-0002-cfg80211-mtk-extend-CAC-time-for-weather-radar-chann.patch \
     file://mtk-0003-mac80211-mtk-it-s-invalid-case-when-frag_threshold-i.patch \
     file://mtk-0004-mac80211-mtk-correct-legacy-rates-check-in-ieee80211.patch \
     file://mtk-0005-mac80211-mtk-airtime_flags-depends-on-NL80211_EXT_FE.patch \
@@ -72,6 +72,7 @@
     file://mtk-0015-mac80211-mtk-track-obss-color-bitmap.patch \
     file://mtk-0016-mac80211-mtk-ageout-color-bitmap.patch \
     file://mtk-0017-mac80211-mtk-update-max_bssid_indicator-based-on-rea.patch \
+    file://mtk-0018-mac80211-support-configurable-addba-resp-time.patch \
     file://mtk-9900-mac80211-mtk-mask-kernel-version-limitation-and-fill.patch \
     file://mtk-9901-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch \
     file://mtk-9902-mac80211-mtk-add-support-for-letting-drivers-registe.patch \
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
index c927e1a..91d65d7 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
@@ -1,7 +1,7 @@
-From 31a7471ec1e183deafd9b28fd62cca3c25f79633 Mon Sep 17 00:00:00 2001
+From 15d734c77b25451efdf3bb1bcd5e687bc429a852 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Fri, 10 Feb 2023 17:39:23 +0800
-Subject: [PATCH 01/22] wifi: mt76: mt7996: add eht rx rate support
+Subject: [PATCH 01/11] wifi: mt76: mt7996: add eht rx rate support
 
 Add support to report eht rx rate.
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch
similarity index 77%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch
index d723e62..8ab501f 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch
@@ -1,20 +1,19 @@
-From 61c13ad2aacdc077bc3729090702821d4777530a Mon Sep 17 00:00:00 2001
+From 83d30a89d61ee914b23d77256e993e9521de5cbc Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Wed, 15 Feb 2023 18:38:04 +0800
-Subject: [PATCH 03/22] wifi: mt76: mt7996: move radio enable command to
- mt7996_start()
+Subject: [PATCH 02/11] wifi: mt76: mt7996: move radio ctrl commands to proper
+ functions
 
-The radio enable and disable commands are used for per-phy radio, so
-move them into mt7996_start() and mt7996_stop(), respectively.
+Move radio enable/disable commands into functions for configuring
+per-phy radio.
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: I610b170f5198e085eb86dbd371ee0745ac6ff50f
 ---
  mt7996/main.c | 11 ++++++-----
  1 file changed, 6 insertions(+), 5 deletions(-)
 
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 136a0c28..28b63d44 100644
+index f306e9c5..e7c97d2f 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -43,6 +43,10 @@ int mt7996_run(struct ieee80211_hw *hw)
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch
new file mode 100644
index 0000000..4342d73
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch
@@ -0,0 +1,198 @@
+From 20c8d7bfeb91be51129e7e98213db441a62d6d95 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Wed, 31 May 2023 18:31:41 +0800
+Subject: [PATCH 03/11] wifi: mt76: connac: add support for dsp firmware
+ download
+
+Add FW_START_WORKING_PDA_DSP for the indication of starting DSP
+firmware download, which is for phy-related control.
+The firmware is transparent to the driver, but it's necessary for the
+firmware download process.
+
+Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I35666504cfe7bf213c8f8f0c0223b3089372f2ab
+---
+v2:
+  - merge two commits
+  - move main load ram code to a regular function
+v3:
+  - remove all macros to directly call __mt7996_load_ram()
+  - add back missing code which records fw_version to wiphy
+---
+ mt76_connac_mcu.h |  1 +
+ mt7996/mcu.c      | 67 +++++++++++++++++++++++------------------------
+ mt7996/mt7996.h   |  7 +++++
+ mt7996/pci.c      |  1 +
+ 4 files changed, 42 insertions(+), 34 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 91d98eff..d2a3d56b 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -22,6 +22,7 @@
+ 
+ #define FW_START_OVERRIDE		BIT(0)
+ #define FW_START_WORKING_PDA_CR4	BIT(2)
++#define FW_START_WORKING_PDA_DSP	BIT(3)
+ 
+ #define PATCH_SEC_NOT_SUPPORT		GENMASK(31, 0)
+ #define PATCH_SEC_TYPE_MASK		GENMASK(15, 0)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 88e2f9d0..545cc987 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2155,7 +2155,7 @@ out:
+ static int
+ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 			     const struct mt7996_fw_trailer *hdr,
+-			     const u8 *data, bool is_wa)
++			     const u8 *data, enum mt7996_ram_type type)
+ {
+ 	int i, offset = 0;
+ 	u32 override = 0, option = 0;
+@@ -2167,8 +2167,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 
+ 		region = (const struct mt7996_fw_region *)((const u8 *)hdr -
+ 			 (hdr->n_region - i) * sizeof(*region));
++		/* DSP and WA use same mode */
+ 		mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
+-						   region->feature_set, is_wa);
++						   region->feature_set,
++						   type != MT7996_RAM_TYPE_WM);
+ 		len = le32_to_cpu(region->len);
+ 		addr = le32_to_cpu(region->addr);
+ 
+@@ -2195,19 +2197,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 	if (override)
+ 		option |= FW_START_OVERRIDE;
+ 
+-	if (is_wa)
++	if (type == MT7996_RAM_TYPE_WA)
+ 		option |= FW_START_WORKING_PDA_CR4;
++	else if (type == MT7996_RAM_TYPE_DSP)
++		option |= FW_START_WORKING_PDA_DSP;
+ 
+ 	return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
+ }
+ 
+-static int mt7996_load_ram(struct mt7996_dev *dev)
++static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
++			     const char *fw_file, enum mt7996_ram_type ram_type)
+ {
+ 	const struct mt7996_fw_trailer *hdr;
+ 	const struct firmware *fw;
+ 	int ret;
+ 
+-	ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
++	ret = request_firmware(&fw, fw_file, dev->mt76.dev);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -2217,37 +2222,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+ 		goto out;
+ 	}
+ 
+-	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+-	dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+-		 hdr->fw_ver, hdr->build_date);
++	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
++	dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n",
++		 fw_type, hdr->fw_ver, hdr->build_date);
+ 
+-	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
++	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type);
+ 	if (ret) {
+-		dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
+-		goto out;
+-	}
+-
+-	release_firmware(fw);
+-
+-	ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
+-	if (ret)
+-		return ret;
+-
+-	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+-		dev_err(dev->mt76.dev, "Invalid firmware\n");
+-		ret = -EINVAL;
+-		goto out;
+-	}
+-
+-	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+-	dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+-		 hdr->fw_ver, hdr->build_date);
+-
+-	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
+-	if (ret) {
+-		dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
++		dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type);
+ 		goto out;
+ 	}
+ 
+@@ -2261,6 +2242,24 @@ out:
+ 	return ret;
+ }
+ 
++static int mt7996_load_ram(struct mt7996_dev *dev)
++{
++	int ret;
++
++	ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
++				MT7996_RAM_TYPE_WM);
++	if (ret)
++		return ret;
++
++	ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP,
++				MT7996_RAM_TYPE_DSP);
++	if (ret)
++		return ret;
++
++	return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA,
++				 MT7996_RAM_TYPE_WA);
++}
++
+ static int
+ mt7996_firmware_state(struct mt7996_dev *dev, bool wa)
+ {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 4d7dcb95..7dfdc738 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -29,6 +29,7 @@
+ 
+ #define MT7996_FIRMWARE_WA		"mediatek/mt7996/mt7996_wa.bin"
+ #define MT7996_FIRMWARE_WM		"mediatek/mt7996/mt7996_wm.bin"
++#define MT7996_FIRMWARE_DSP		"mediatek/mt7996/mt7996_dsp.bin"
+ #define MT7996_ROM_PATCH		"mediatek/mt7996/mt7996_rom_patch.bin"
+ 
+ #define MT7996_EEPROM_DEFAULT		"mediatek/mt7996/mt7996_eeprom.bin"
+@@ -52,6 +53,12 @@ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+ struct mt7996_dfs_pattern;
+ 
++enum mt7996_ram_type {
++	MT7996_RAM_TYPE_WM,
++	MT7996_RAM_TYPE_WA,
++	MT7996_RAM_TYPE_DSP,
++};
++
+ enum mt7996_txq_id {
+ 	MT7996_TXQ_FWDL = 16,
+ 	MT7996_TXQ_MCU_WM,
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 64aee3fb..c5301050 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
+ MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
++MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
+ MODULE_FIRMWARE(MT7996_ROM_PATCH);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch
new file mode 100644
index 0000000..a4e17a9
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch
@@ -0,0 +1,51 @@
+From 3c7a5592ea211f5ddb2f6bbd6ba8720c74faf459 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Thu, 2 Mar 2023 15:44:52 +0800
+Subject: [PATCH 04/11] wifi: mt76: mt7996: fix bss wlan_idx when sending
+ bss_info command
+
+The bmc_tx_wlan_idx should be the wlan_idx of the current bss rather
+than peer AP's wlan_idx, otherwise there will appear some frame
+decryption problems on station mode.
+
+Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
+Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/mcu.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 545cc987..6706d38c 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -712,6 +712,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 	struct cfg80211_chan_def *chandef = &phy->chandef;
+ 	struct mt76_connac_bss_basic_tlv *bss;
+ 	u32 type = CONNECTION_INFRA_AP;
++	u16 sta_wlan_idx = wlan_idx;
+ 	struct tlv *tlv;
+ 	int idx;
+ 
+@@ -731,7 +732,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 				struct mt76_wcid *wcid;
+ 
+ 				wcid = (struct mt76_wcid *)sta->drv_priv;
+-				wlan_idx = wcid->idx;
++				sta_wlan_idx = wcid->idx;
+ 			}
+ 			rcu_read_unlock();
+ 		}
+@@ -751,7 +752,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 	bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
+ 	bss->dtim_period = vif->bss_conf.dtim_period;
+ 	bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
+-	bss->sta_idx = cpu_to_le16(wlan_idx);
++	bss->sta_idx = cpu_to_le16(sta_wlan_idx);
+ 	bss->conn_type = cpu_to_le32(type);
+ 	bss->omac_idx = mvif->omac_idx;
+ 	bss->band_idx = mvif->band_idx;
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
new file mode 100644
index 0000000..d4968dd
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
@@ -0,0 +1,29 @@
+From 56d84272851f6c77cf68186bc8906de0558d2e5b Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 17 Mar 2023 11:08:04 +0800
+Subject: [PATCH 05/11] wifi: mt76: mt7996: init he and eht cap for AP_VLAN
+
+Init he and eht capabilities for AP_VLAN type. Without this patch, the
+BA response from AP_VLAN will not include the ADDBA extension tag.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/init.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index f1b48cdd..004575a0 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -808,6 +808,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
+ 		switch (i) {
+ 		case NL80211_IFTYPE_STATION:
+ 		case NL80211_IFTYPE_AP:
++		case NL80211_IFTYPE_AP_VLAN:
+ #ifdef CONFIG_MAC80211_MESH
+ 		case NL80211_IFTYPE_MESH_POINT:
+ #endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch
new file mode 100644
index 0000000..348a04a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch
@@ -0,0 +1,30 @@
+From 1e7bbf8c04d60eb6cd234990f94da73bccd73118 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 27 Mar 2023 14:30:25 +0800
+Subject: [PATCH 06/11] wifi: mt76: mt7996: enable VHT extended NSS BW feature
+
+Set SUPPORTS_VHT_EXT_NSS_BW to let the max BW capability correctly be
+parsed by different devices.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 004575a0..8247153d 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -217,6 +217,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ 		phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
+ 			IEEE80211_HT_MPDU_DENSITY_1;
++
++		ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
+ 	}
+ 
+ 	mt76_set_stream_caps(phy->mt76, true);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-set-txd-v1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-set-txd-v1.patch
deleted file mode 100644
index f9cdd1a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-set-txd-v1.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From a25714fa7b610430f9aa3d4ec24647eaea505d35 Mon Sep 17 00:00:00 2001
-From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Mon, 6 Feb 2023 10:40:33 +0800
-Subject: [PATCH 06/22] wifi: mt76: mt7996: set txd v1
-
----
- mt7996/mac.c | 3 +++
- mt7996/mac.h | 3 ++-
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 23cbfdde..420c7403 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1110,6 +1110,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 	struct mt76_txwi_cache *t;
- 	int id, i, pid, nbuf = tx_info->nbuf - 1;
- 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
-+	__le32 *txd = (__le32 *)txwi_ptr;
- 	u8 *txwi = (u8 *)txwi_ptr;
- 
- 	if (unlikely(tx_info->skb->len <= ETH_HLEN))
-@@ -1141,6 +1142,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
- 				      pid, qid, 0);
- 
-+	txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
-+
- 	txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
- 	for (i = 0; i < nbuf; i++) {
- 		txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index bc4e6c55..9ab8e8d2 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -173,7 +173,8 @@ enum tx_mgnt_type {
- 
- #define MT_TXD0_Q_IDX			GENMASK(31, 25)
- #define MT_TXD0_PKT_FMT			GENMASK(24, 23)
--#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(22, 16)
-+#define MT_TXD0_VER			GENMASK(22, 19)
-+#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(18, 16)
- #define MT_TXD0_TX_BYTES		GENMASK(15, 0)
- 
- #define MT_TXD1_FIXED_RATE		BIT(31)
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch
new file mode 100644
index 0000000..8021427
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch
@@ -0,0 +1,261 @@
+From edca876e34fc2696e8f855c2d05036fa79a05f8f Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Thu, 1 Jun 2023 12:01:10 +0800
+Subject: [PATCH 07/11] wifi: mt76: connac: add support to set ifs time by mcu
+ command
+
+There's a race between driver and fw on some tx/rx control registers
+when setting ifs, which will cause accidental hw queue pause problems.
+Avoid this by setting ifs time with bss_info mcu command.
+
+Reviewed-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: Ib6477462a35df84a89f113a4db0e6aef5154c6a8
+---
+v2:
+  - merge two commits
+  - change bool a_band to use is_2ghz
+---
+ mt76_connac_mcu.h |  1 +
+ mt7996/mac.c      | 27 ++-------------------------
+ mt7996/main.c     |  5 ++---
+ mt7996/mcu.c      | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      | 17 +++++++++++++++++
+ mt7996/mt7996.h   |  3 ++-
+ 6 files changed, 70 insertions(+), 29 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index d2a3d56b..b91262ee 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1288,6 +1288,7 @@ enum {
+ 	UNI_BSS_INFO_UAPSD = 19,
+ 	UNI_BSS_INFO_PS = 21,
+ 	UNI_BSS_INFO_BCNFT = 22,
++	UNI_BSS_INFO_IFS_TIME = 23,
+ 	UNI_BSS_INFO_OFFLOAD = 25,
+ 	UNI_BSS_INFO_MLD = 26,
+ };
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 23cbfdde..2da61d2e 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1612,20 +1612,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy)
+ 	mt7996_mcu_get_chan_mib_info(phy, true);
+ }
+ 
+-void mt7996_mac_set_timing(struct mt7996_phy *phy)
++void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
+ {
+ 	s16 coverage_class = phy->coverage_class;
+ 	struct mt7996_dev *dev = phy->dev;
+ 	struct mt7996_phy *phy2 = mt7996_phy2(dev);
+ 	struct mt7996_phy *phy3 = mt7996_phy3(dev);
+-	u32 val, reg_offset;
++	u32 reg_offset;
+ 	u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
+ 		  FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
+ 	u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
+ 		   FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
+ 	u8 band_idx = phy->mt76->band_idx;
+ 	int offset;
+-	bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
+ 
+ 	if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
+ 		return;
+@@ -1638,34 +1637,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy)
+ 		coverage_class = max_t(s16, coverage_class,
+ 				       phy3->coverage_class);
+ 
+-	mt76_set(dev, MT_ARB_SCR(band_idx),
+-		 MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+-	udelay(1);
+-
+ 	offset = 3 * coverage_class;
+ 	reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
+ 		     FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
+ 
+ 	mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset);
+ 	mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset);
+-	mt76_wr(dev, MT_TMAC_ICR0(band_idx),
+-		FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
+-		FIELD_PREP(MT_IFS_RIFS, 2) |
+-		FIELD_PREP(MT_IFS_SIFS, 10) |
+-		FIELD_PREP(MT_IFS_SLOT, phy->slottime));
+-
+-	if (!a_band)
+-		mt76_wr(dev, MT_TMAC_ICR1(band_idx),
+-			FIELD_PREP(MT_IFS_EIFS_CCK, 314));
+-
+-	if (phy->slottime < 20 || a_band)
+-		val = MT7996_CFEND_RATE_DEFAULT;
+-	else
+-		val = MT7996_CFEND_RATE_11B;
+-
+-	mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val);
+-	mt76_clear(dev, MT_ARB_SCR(band_idx),
+-		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
+ }
+ 
+ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band)
+diff --git a/mt7996/main.c b/mt7996/main.c
+index e7c97d2f..786c3fbc 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -287,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy)
+ 	if (ret)
+ 		goto out;
+ 
+-	mt7996_mac_set_timing(phy);
+ 	ret = mt7996_dfs_init_radar_detector(phy);
+ 	mt7996_mac_cca_stats_reset(phy);
+ 
+@@ -564,7 +563,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ 
+ 		if (slottime != phy->slottime) {
+ 			phy->slottime = slottime;
+-			mt7996_mac_set_timing(phy);
++			mt7996_mcu_set_timing(phy, vif);
+ 		}
+ 	}
+ 
+@@ -904,7 +903,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
+ 
+ 	mutex_lock(&dev->mt76.mutex);
+ 	phy->coverage_class = max_t(s16, coverage_class, 0);
+-	mt7996_mac_set_timing(phy);
++	mt7996_mac_set_coverage_class(phy);
+ 	mutex_unlock(&dev->mt76.mutex);
+ }
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6706d38c..0ede9769 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -701,6 +701,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+ 				 sizeof(req), true);
+ }
+ 
++static void
++mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
++{
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct mt7996_phy *phy = mvif->phy;
++	struct bss_ifs_time_tlv *ifs_time;
++	struct tlv *tlv;
++	bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
++
++	tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time));
++
++	ifs_time = (struct bss_ifs_time_tlv *)tlv;
++	ifs_time->slot_valid = true;
++	ifs_time->sifs_valid = true;
++	ifs_time->rifs_valid = true;
++	ifs_time->eifs_valid = true;
++
++	ifs_time->slot_time = cpu_to_le16(phy->slottime);
++	ifs_time->sifs_time = cpu_to_le16(10);
++	ifs_time->rifs_time = cpu_to_le16(2);
++	ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84);
++
++	if (is_2ghz) {
++		ifs_time->eifs_cck_valid = true;
++		ifs_time->eifs_cck_time = cpu_to_le16(314);
++	}
++}
++
+ static int
+ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 			 struct ieee80211_vif *vif,
+@@ -826,6 +854,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
+ 		mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
+ 		mt7996_mcu_bss_ra_tlv(skb, vif, phy);
+ 		mt7996_mcu_bss_txcmd_tlv(skb, true);
++		mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
+ 
+ 		if (vif->bss_conf.he_support)
+ 			mt7996_mcu_bss_he_tlv(skb, vif, phy);
+@@ -838,6 +867,23 @@ out:
+ 				     MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
+ }
+ 
++int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
++{
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct mt7996_dev *dev = phy->dev;
++	struct sk_buff *skb;
++
++	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
++					 MT7996_BSS_UPDATE_MAX_SIZE);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
++
++	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
++				     MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
++}
++
+ static int
+ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ 		  struct ieee80211_ampdu_params *params,
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index d7075a4d..078f8285 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -317,6 +317,22 @@ struct bss_sec_tlv {
+ 	u8 __rsv2[1];
+ } __packed;
+ 
++struct bss_ifs_time_tlv {
++	__le16 tag;
++	__le16 len;
++	u8 slot_valid;
++	u8 sifs_valid;
++	u8 rifs_valid;
++	u8 eifs_valid;
++	__le16 slot_time;
++	__le16 sifs_time;
++	__le16 rifs_time;
++	__le16 eifs_time;
++	u8 eifs_cck_valid;
++	u8 rsv;
++	__le16 eifs_cck_time;
++} __packed;
++
+ struct bss_power_save {
+ 	__le16 tag;
+ 	__le16 len;
+@@ -552,6 +568,7 @@ enum {
+ 					 sizeof(struct bss_txcmd_tlv) +		\
+ 					 sizeof(struct bss_power_save) +	\
+ 					 sizeof(struct bss_sec_tlv) +		\
++					 sizeof(struct bss_ifs_time_tlv) +	\
+ 					 sizeof(struct bss_mld_tlv))
+ 
+ #define MT7996_STA_UPDATE_MAX_SIZE	(sizeof(struct sta_req_hdr) +		\
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 7dfdc738..42892f06 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -463,6 +463,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
+ 			    const struct mt7996_dfs_pattern *pattern);
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
++int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
+ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 		       u8 rx_sel, u8 val);
+@@ -526,7 +527,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ 			   struct sk_buff *skb, struct mt76_wcid *wcid,
+ 			   struct ieee80211_key_conf *key, int pid,
+ 			   enum mt76_txq_id qid, u32 changed);
+-void mt7996_mac_set_timing(struct mt7996_phy *phy);
++void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
+ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ 		       struct ieee80211_sta *sta);
+ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch
new file mode 100644
index 0000000..24d2bfd
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch
@@ -0,0 +1,37 @@
+From 9cf96fa56a20d30f7e46e96d9c48c3568fbf11af Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Tue, 7 Mar 2023 17:05:01 +0800
+Subject: [PATCH 08/11] wifi: mt76: mt7996: use correct phy for background
+ radar event
+
+If driver directly uses the band_idx reported from the radar event to
+access mt76_phy array, it will get the wrong phy for background radar.
+Fix this by adjusting the statement.
+
+Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/mcu.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 0ede9769..20519bff 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
+ 		return;
+ 
+-	mphy = dev->mt76.phys[r->band_idx];
++	if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
++		mphy = dev->rdd2_phy->mt76;
++	else
++		mphy = dev->mt76.phys[r->band_idx];
++
+ 	if (!mphy)
+ 		return;
+ 
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-add-dsp-firmware-download.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-add-dsp-firmware-download.patch
deleted file mode 100644
index eb65330..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-add-dsp-firmware-download.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From 9b6e04ff1ac32161c6aacb939b2ff51bdced9629 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 17 Feb 2023 14:13:38 +0800
-Subject: [PATCH 09/22] wifi: mt76: mt7996: add dsp firmware download
-
-Add DSP firmware for phy related control. Without this patch,the
-firmware state would not be ready.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt76_connac_mcu.h |  1 +
- mt7996/mcu.c      | 94 +++++++++++++++++++++--------------------------
- mt7996/mt7996.h   |  7 ++++
- mt7996/pci.c      |  1 +
- 4 files changed, 50 insertions(+), 53 deletions(-)
-
-diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index c5c48349..fbb1206f 100644
---- a/mt76_connac_mcu.h
-+++ b/mt76_connac_mcu.h
-@@ -22,6 +22,7 @@
- 
- #define FW_START_OVERRIDE		BIT(0)
- #define FW_START_WORKING_PDA_CR4	BIT(2)
-+#define FW_START_WORKING_PDA_DSP	BIT(3)
- 
- #define PATCH_SEC_NOT_SUPPORT		GENMASK(31, 0)
- #define PATCH_SEC_TYPE_MASK		GENMASK(15, 0)
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index f3fd2fd4..73d5dedf 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2241,7 +2241,7 @@ out:
- static int
- mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
- 			     const struct mt7996_fw_trailer *hdr,
--			     const u8 *data, bool is_wa)
-+			     const u8 *data, enum mt7996_ram_type type)
- {
- 	int i, offset = 0;
- 	u32 override = 0, option = 0;
-@@ -2253,8 +2253,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
- 
- 		region = (const struct mt7996_fw_region *)((const u8 *)hdr -
- 			 (hdr->n_region - i) * sizeof(*region));
-+		/* DSP and WA use same mode */
- 		mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
--						   region->feature_set, is_wa);
-+						   region->feature_set,
-+						   type != MT7996_RAM_TYPE_WM);
- 		len = le32_to_cpu(region->len);
- 		addr = le32_to_cpu(region->addr);
- 
-@@ -2281,8 +2283,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
- 	if (override)
- 		option |= FW_START_OVERRIDE;
- 
--	if (is_wa)
-+	if (type == MT7996_RAM_TYPE_WA)
- 		option |= FW_START_WORKING_PDA_CR4;
-+	else if (type == MT7996_RAM_TYPE_DSP)
-+		option |= FW_START_WORKING_PDA_DSP;
- 
- 	return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
- }
-@@ -2293,56 +2297,40 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
- 	const struct firmware *fw;
- 	int ret;
- 
--	ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
--	if (ret)
--		return ret;
--
--	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
--		dev_err(dev->mt76.dev, "Invalid firmware\n");
--		ret = -EINVAL;
--		goto out;
--	}
--
--	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
--
--	dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
--		 hdr->fw_ver, hdr->build_date);
--
--	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
--	if (ret) {
--		dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
--		goto out;
--	}
--
--	release_firmware(fw);
--
--	ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
--	if (ret)
--		return ret;
--
--	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
--		dev_err(dev->mt76.dev, "Invalid firmware\n");
--		ret = -EINVAL;
--		goto out;
--	}
--
--	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
--
--	dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
--		 hdr->fw_ver, hdr->build_date);
--
--	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
--	if (ret) {
--		dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
--		goto out;
--	}
--
--	snprintf(dev->mt76.hw->wiphy->fw_version,
--		 sizeof(dev->mt76.hw->wiphy->fw_version),
--		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
--
--out:
--	release_firmware(fw);
-+#define LOAD_RAM(_type) \
-+	do {									\
-+		ret = request_firmware(&fw, MT7996_FIRMWARE_##_type, dev->mt76.dev);	\
-+		if (ret)							\
-+			return ret;						\
-+										\
-+		if (!fw || !fw->data || fw->size < sizeof(*hdr)) {		\
-+			dev_err(dev->mt76.dev, "Invalid firmware\n");		\
-+			release_firmware(fw);					\
-+			return -EINVAL;						\
-+		}								\
-+										\
-+		hdr = (const struct mt7996_fw_trailer *)			\
-+				(fw->data + fw->size - sizeof(*hdr));		\
-+										\
-+		dev_info(dev->mt76.dev,						\
-+			 "%s Firmware Version: %.10s, Build Time: %.15s\n",	\
-+			 #_type, hdr->fw_ver, hdr->build_date);			\
-+										\
-+		ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data,		\
-+						   MT7996_RAM_TYPE_##_type);    \
-+		if (ret) {							\
-+			dev_err(dev->mt76.dev, "Failed to start %s firmware\n", #_type);\
-+			release_firmware(fw);					\
-+			return ret;						\
-+		}								\
-+										\
-+		release_firmware(fw);						\
-+	} while (0)
-+
-+	LOAD_RAM(WM);
-+	LOAD_RAM(DSP);
-+	LOAD_RAM(WA);
-+#undef LOAD_RAM
- 
- 	return ret;
- }
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 36337808..ab4521a4 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -29,6 +29,7 @@
- 
- #define MT7996_FIRMWARE_WA		"mediatek/mt7996/mt7996_wa.bin"
- #define MT7996_FIRMWARE_WM		"mediatek/mt7996/mt7996_wm.bin"
-+#define MT7996_FIRMWARE_DSP		"mediatek/mt7996/mt7996_dsp.bin"
- #define MT7996_ROM_PATCH		"mediatek/mt7996/mt7996_rom_patch.bin"
- 
- #define MT7996_EEPROM_DEFAULT		"mediatek/mt7996/mt7996_eeprom.bin"
-@@ -59,6 +60,12 @@ struct mt7996_sta;
- struct mt7996_dfs_pulse;
- struct mt7996_dfs_pattern;
- 
-+enum mt7996_ram_type {
-+	MT7996_RAM_TYPE_WM = 0,
-+	MT7996_RAM_TYPE_WA,
-+	MT7996_RAM_TYPE_DSP,
-+};
-+
- enum mt7996_txq_id {
- 	MT7996_TXQ_FWDL = 16,
- 	MT7996_TXQ_MCU_WM,
-diff --git a/mt7996/pci.c b/mt7996/pci.c
-index 64aee3fb..c5301050 100644
---- a/mt7996/pci.c
-+++ b/mt7996/pci.c
-@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
- MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
- MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
- MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
-+MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
- MODULE_FIRMWARE(MT7996_ROM_PATCH);
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch
new file mode 100644
index 0000000..6ffa018
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch
@@ -0,0 +1,44 @@
+From f9ac23ac488c0dafceab97c8d39a22904cf78f77 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 23 Mar 2023 15:16:14 +0800
+Subject: [PATCH 09/11] wifi: mt76: mt7996: fix WA event ring size
+
+Fix rx ring size of WA event to get rid of event loss and queue overflow
+problems.
+
+Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/dma.c    | 2 +-
+ mt7996/mt7996.h | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 53414346..fbedaacf 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -293,7 +293,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	/* event from WA */
+ 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
+ 			       MT_RXQ_ID(MT_RXQ_MCU_WA),
+-			       MT7996_RX_MCU_RING_SIZE,
++			       MT7996_RX_MCU_RING_SIZE_WA,
+ 			       MT_RX_BUF_SIZE,
+ 			       MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
+ 	if (ret)
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 42892f06..a3bd85d3 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -26,6 +26,7 @@
+ 
+ #define MT7996_RX_RING_SIZE		1536
+ #define MT7996_RX_MCU_RING_SIZE		512
++#define MT7996_RX_MCU_RING_SIZE_WA	1024
+ 
+ #define MT7996_FIRMWARE_WA		"mediatek/mt7996/mt7996_wa.bin"
+ #define MT7996_FIRMWARE_WM		"mediatek/mt7996/mt7996_wm.bin"
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-muru-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch
similarity index 83%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-muru-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch
index 1854421..c0f61b7 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-add-muru-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-muru-support.patch
@@ -1,23 +1,22 @@
-From 85fb9bc9f85a5e64d88db85fbfdef968d037fada Mon Sep 17 00:00:00 2001
+From 8a284ffc268754a8e941888ce6f1b506f3c7564c Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
 Date: Mon, 28 Nov 2022 14:36:09 +0800
-Subject: [PATCH 05/22] wifi: mt76: mt7996: add muru support
+Subject: [PATCH 10/11] wifi: mt76: mt7996: add muru support
 
-Add sta_rec_muru() and related phy cap for MU and RU support.
+Add sta_rec_muru() fw command to support MU-MIMO and OFDMA features.
 
 Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
-Change-Id: I2206a9bb6fd6e50f4bf1380a8bea19920f1b7bfd
 ---
  mt76_connac_mcu.h |  3 ++-
- mt7996/mcu.c      | 57 ++++++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 58 insertions(+), 2 deletions(-)
+ mt7996/mcu.c      | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 57 insertions(+), 2 deletions(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 91d98eff..8580ca59 100644
+index b91262ee..6249de57 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -518,7 +518,8 @@ struct sta_rec_muru {
+@@ -519,7 +519,8 @@ struct sta_rec_muru {
  		u8 uo_ra;
  		u8 he_2x996_tone;
  		u8 rx_t_frame_11ac;
@@ -28,10 +27,10 @@
  
  	struct {
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 88e2f9d0..6812a47b 100644
+index 20519bff..611f6450 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1050,6 +1050,60 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1101,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
  	}
  }
  
@@ -50,7 +49,6 @@
 +	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
 +
 +	muru = (struct sta_rec_muru *)tlv;
-+
 +	muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
 +			       vif->bss_conf.he_mu_beamformer ||
 +			       vif->bss_conf.vht_mu_beamformer ||
@@ -92,7 +90,7 @@
  static inline bool
  mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
  			struct ieee80211_sta *sta, bool bfee)
-@@ -1727,7 +1781,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -1778,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  		mt7996_mcu_sta_he_6g_tlv(skb, sta);
  		/* starec eht */
  		mt7996_mcu_sta_eht_tlv(skb, sta);
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
deleted file mode 100644
index caa9b1a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From ee3a2aa33145d17d3be17af85583437f079e91fb Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Thu, 2 Mar 2023 15:44:52 +0800
-Subject: [PATCH 10/22] wifi: mt76: mt7996: fix icv error when enable AP and
- STA simultaneously
-
-Fix mcu command content to prevent ICV error
-The bmc_tx_wlan_idx needs to be the vif index rather
-than peer AP's index.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt7996/mcu.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 73d5dedf..6d11bc1a 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -743,6 +743,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- 	struct cfg80211_chan_def *chandef = &phy->chandef;
- 	struct mt76_connac_bss_basic_tlv *bss;
- 	u32 type = CONNECTION_INFRA_AP;
-+	u16 sta_wlan_idx = wlan_idx;
- 	struct tlv *tlv;
- 	int idx;
- 
-@@ -762,7 +763,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- 				struct mt76_wcid *wcid;
- 
- 				wcid = (struct mt76_wcid *)sta->drv_priv;
--				wlan_idx = wcid->idx;
-+				sta_wlan_idx = wcid->idx;
- 			}
- 			rcu_read_unlock();
- 		}
-@@ -782,7 +783,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
- 	bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
- 	bss->dtim_period = vif->bss_conf.dtim_period;
- 	bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
--	bss->sta_idx = cpu_to_le16(wlan_idx);
-+	bss->sta_idx = cpu_to_le16(sta_wlan_idx);
- 	bss->conn_type = cpu_to_le32(type);
- 	bss->omac_idx = mvif->omac_idx;
- 	bss->band_idx = mvif->band_idx;
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch
new file mode 100644
index 0000000..aa039ce
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-increase-tx-token-size.patch
@@ -0,0 +1,30 @@
+From 0cc8d7827510e36978175d84d63cced5f842ff61 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 17 Apr 2023 09:49:53 +0800
+Subject: [PATCH 11/11] wifi: mt76: mt7996: increase tx token size
+
+Align tx token size to proprietary driver, which can improve peak
+throughput under MU performance tests.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/mt7996.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index a3bd85d3..651f53aa 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -36,7 +36,7 @@
+ #define MT7996_EEPROM_DEFAULT		"mediatek/mt7996/mt7996_eeprom.bin"
+ #define MT7996_EEPROM_SIZE		7680
+ #define MT7996_EEPROM_BLOCK_SIZE	16
+-#define MT7996_TOKEN_SIZE		8192
++#define MT7996_TOKEN_SIZE		16384
+ 
+ #define MT7996_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */
+ #define MT7996_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
deleted file mode 100644
index f05fe30..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 9af2057cec3d77aafb4f92b8d1542d88c8ac5efc Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 17 Mar 2023 11:08:04 +0800
-Subject: [PATCH 12/22] wifi: mt76: mt7996: init he and eht cap for AP_VLAN
-
-Add AP_VLAN types in __mt7996_set_stream_he_eht_caps to
-initialize the ht and eht caps. Without this patch, the
-BA response from VLAN AP would not include the ADDBA
-extension tag.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt7996/init.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mt7996/init.c b/mt7996/init.c
-index 9c5d20ad..d44e3ae9 100644
---- a/mt7996/init.c
-+++ b/mt7996/init.c
-@@ -993,6 +993,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
- 		switch (i) {
- 		case NL80211_IFTYPE_STATION:
- 		case NL80211_IFTYPE_AP:
-+		case NL80211_IFTYPE_AP_VLAN:
- #ifdef CONFIG_MAC80211_MESH
- 		case NL80211_IFTYPE_MESH_POINT:
- #endif
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-Fix-using-the-wrong-phy-for-backgro.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-Fix-using-the-wrong-phy-for-backgro.patch
deleted file mode 100644
index 461236e..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-Fix-using-the-wrong-phy-for-backgro.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From b1296ffe7596adf514bc2b5397c946e276e30176 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Tue, 7 Mar 2023 17:05:01 +0800
-Subject: [PATCH 14/22] wifi: mt76: mt7996: Fix using the wrong phy for
- background radar event
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- mt7996/mcu.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index df1ae639..cd86209b 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
- 	if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
- 		return;
- 
--	mphy = dev->mt76.phys[r->band_idx];
-+	if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
-+		mphy = dev->rdd2_phy->mt76;
-+	else
-+		mphy = dev->mt76.phys[r->band_idx];
-+
- 	if (!mphy)
- 		return;
- 
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-set-wcid-in-txp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch
similarity index 70%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-set-wcid-in-txp.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch
index d612bdf..8103127 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-set-wcid-in-txp.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-set-wcid-in-txp.patch
@@ -1,20 +1,21 @@
-From 952869c0b481651e9c125d5cd7c4ea2b255521c5 Mon Sep 17 00:00:00 2001
+From 5e2177e77b9609185f748708332aa6a6fdf4d1f9 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Mon, 6 Mar 2023 15:52:26 +0800
-Subject: [PATCH 11/22] wifi: mt76: mt7996: set wcid in txp
+Subject: [PATCH 14/39] wifi: mt76: mt7996: set wcid in txp
 
 Set correct wcid in txp for SDO to get wtbl.
 
 Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Change-Id: Ie715a659ff52f2d85332158f273d0ee4fe9f4051
 ---
  mt7996/mac.c | 8 +++++---
  1 file changed, 5 insertions(+), 3 deletions(-)
 
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 420c7403..ca163969 100644
+index 2da61d2..bddb84f 100644
 --- a/mt7996/mac.c
 +++ b/mt7996/mac.c
-@@ -1169,10 +1169,12 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -1166,10 +1166,12 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
  	}
  
  	txp->fw.token = cpu_to_le16(id);
@@ -22,7 +23,7 @@
 -		txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
 -	else
 +	if ((is_8023 && is_multicast_ether_addr(tx_info->skb->data)) ||
-+	     is_multicast_ether_addr(hdr->addr1))
++	    (!is_8023 && is_multicast_ether_addr(hdr->addr1)))
  		txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
 +	else
 +		txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
@@ -31,5 +32,5 @@
  
  	/* pass partial skb header to fw */
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
similarity index 90%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
index 50f83e7..ea01cf0 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
@@ -1,7 +1,7 @@
-From 1a55033a534847f9c10ffd52e277378c1ba3e45a Mon Sep 17 00:00:00 2001
+From 5580f05c864aadfad4092fc97a937869dc08eca8 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 16 Feb 2023 00:39:01 +0800
-Subject: [PATCH 02/22] wifi: mt76: mt7996: reduce repeated bss_info and
+Subject: [PATCH 15/39] wifi: mt76: mt7996: reduce repeated bss_info and
  sta_rec commands
 
 Refine the flow of setting bss_info and sta_rec commands to prevent from
@@ -14,10 +14,10 @@
  1 file changed, 6 insertions(+), 15 deletions(-)
 
 diff --git a/mt7996/main.c b/mt7996/main.c
-index f306e9c5..136a0c28 100644
+index 786c3fb..02a33b8 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -246,8 +246,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+@@ -248,8 +248,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
  	struct mt7996_phy *phy = mt7996_hw_phy(hw);
  	int idx = msta->wcid.idx;
  
@@ -63,5 +63,5 @@
  	if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
  		mt7996_mcu_set_tx(dev, vif);
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
similarity index 86%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
index 3f55f11..e6a4f75 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
@@ -1,7 +1,7 @@
-From fb2659a8aa12346cdda4010737f63178040fa513 Mon Sep 17 00:00:00 2001
+From eec83d4410d7c669d9a05bba1a69a742a6ccd490 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 16 Feb 2023 13:53:14 +0800
-Subject: [PATCH 04/22] wifi: mt76: connac: set correct muar_idx for connac3
+Subject: [PATCH 16/39] wifi: mt76: connac: set correct muar_idx for connac3
  chipset
 
 Set the muar_idx to 0xe for the hw bcast/mcast station entry of connac3
@@ -15,7 +15,7 @@
  2 files changed, 8 insertions(+)
 
 diff --git a/mt76_connac.h b/mt76_connac.h
-index 77ca8f05..02acac64 100644
+index 77ca8f0..02acac6 100644
 --- a/mt76_connac.h
 +++ b/mt76_connac.h
 @@ -240,6 +240,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
@@ -31,7 +31,7 @@
  {
  	switch (mt76_chip(dev)) {
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 46f69aa8..5fab6772 100644
+index 46f69aa..5fab677 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -281,6 +281,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
@@ -45,5 +45,5 @@
  				     &hdr.wlan_idx_hi);
  	skb = mt76_mcu_msg_alloc(dev, NULL, len);
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-fill-txwi-by-SW-temporarily.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-fill-txwi-by-SW-temporarily.patch
deleted file mode 100644
index c756ccd..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-fill-txwi-by-SW-temporarily.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From aa539aaae8a95f3e970ad8e1f5a7381bb249ad7e Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 17 Mar 2023 11:16:44 +0800
-Subject: [PATCH 16/22] wifi: mt76: mt7996: fill txwi by SW temporarily
-
-If use WA to fill TXD, it cannot ping pass.
-Remove this patch after bug fix.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- mt7996/mac.c | 8 +++-----
- 1 file changed, 3 insertions(+), 5 deletions(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index ca163969..7059a4e1 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1138,9 +1138,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
- 	memset(txwi_ptr, 0, MT_TXD_SIZE);
- 	/* Transmit non qos data by 802.11 header and need to fill txd by host*/
--	if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
--		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
--				      pid, qid, 0);
-+	mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
-+			      pid, qid, 0);
- 
- 	txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
- 
-@@ -1153,8 +1152,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 
- 	txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
- 
--	if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
--		txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
-+	txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
- 
- 	if (!key)
- 		txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-add-thermal-protection-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch
similarity index 91%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-add-thermal-protection-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch
index 526edc7..bcc5d51 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-add-thermal-protection-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-add-thermal-protection-support.patch
@@ -1,7 +1,7 @@
-From 7d85212987815786ceff28379015a6bb23012dc3 Mon Sep 17 00:00:00 2001
+From 1fa1645ef7621981c7e87d27b9a7816f3485d3db Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Thu, 2 Feb 2023 21:20:31 +0800
-Subject: [PATCH 07/22] wifi: mt76: mt7996: add thermal protection support
+Subject: [PATCH 17/39] wifi: mt76: mt7996: add thermal protection support
 
 This commit includes the following changes:
 1. implement MTK thermal protection driver API
@@ -18,10 +18,10 @@
  6 files changed, 277 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 8580ca59..c5c48349 100644
+index 6249de5..30c9a5d 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1009,6 +1009,7 @@ enum {
+@@ -1010,6 +1010,7 @@ enum {
  	MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
  	MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
  	MCU_UNI_EVENT_RDD_REPORT = 0x11,
@@ -30,7 +30,7 @@
  
  #define MCU_UNI_CMD_EVENT			BIT(1)
 diff --git a/mt7996/init.c b/mt7996/init.c
-index f1b48cdd..53852ffc 100644
+index 8247153..c072b09 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
 @@ -42,6 +42,98 @@ static const struct ieee80211_iface_combination if_comb[] = {
@@ -132,7 +132,7 @@
  static void mt7996_led_set_config(struct led_classdev *led_cdev,
  				  u8 delay_on, u8 delay_off)
  {
-@@ -389,6 +481,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+@@ -391,6 +483,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
  	if (ret)
  		goto error;
  
@@ -143,7 +143,7 @@
  	ret = mt7996_init_debugfs(phy);
  	if (ret)
  		goto error;
-@@ -409,6 +505,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
+@@ -411,6 +507,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
  	if (!phy)
  		return;
  
@@ -152,7 +152,7 @@
  	mphy = phy->dev->mt76.phys[band];
  	mt76_unregister_phy(mphy);
  	ieee80211_free_hw(mphy->hw);
-@@ -879,6 +977,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -882,6 +980,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
  	if (ret)
  		return ret;
  
@@ -163,7 +163,7 @@
  	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
  
  	ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
-@@ -902,6 +1004,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
+@@ -905,6 +1007,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
  {
  	mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
  	mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
@@ -172,7 +172,7 @@
  	mt76_unregister_device(&dev->mt76);
  	mt7996_mcu_exit(dev);
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 28b63d44..fbb7270d 100644
+index 02a33b8..9c80839 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -51,6 +51,14 @@ int mt7996_run(struct ieee80211_hw *hw)
@@ -191,10 +191,10 @@
  
  	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6812a47b..325051bd 100644
+index c50dcce..c308d86 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -443,6 +443,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -447,6 +447,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
  	}
  }
  
@@ -229,7 +229,7 @@
  static void
  mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
  {
-@@ -487,6 +515,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -491,6 +519,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
  	case MCU_UNI_EVENT_RDD_REPORT:
  		mt7996_mcu_rx_radar_detected(dev, skb);
  		break;
@@ -239,7 +239,7 @@
  	default:
  		break;
  	}
-@@ -3178,6 +3209,81 @@ out:
+@@ -3217,6 +3248,81 @@ out:
  	return 0;
  }
  
@@ -322,7 +322,7 @@
  {
  	struct {
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index d7075a4d..778deedf 100644
+index 078f828..f235175 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
 @@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
@@ -377,7 +377,7 @@
  enum mt7996_chan_mib_offs {
  	UNI_MIB_OBSS_AIRTIME = 26,
  	UNI_MIB_NON_WIFI_TIME = 27,
-@@ -642,6 +680,12 @@ enum{
+@@ -659,6 +697,12 @@ enum{
  	UNI_CMD_SR_SET_SIGA = 0xd0,
  };
  
@@ -391,10 +391,10 @@
  	UNI_CMD_ACCESS_REG_BASIC = 0x0,
  	UNI_CMD_ACCESS_RF_REG_BASIC,
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 4d7dcb95..36337808 100644
+index 651f53a..071031b 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -47,6 +47,13 @@
+@@ -49,6 +49,13 @@
  #define MT7996_BASIC_RATES_TBL		11
  #define MT7996_BEACON_RATES_TBL		25
  
@@ -408,7 +408,7 @@
  struct mt7996_vif;
  struct mt7996_sta;
  struct mt7996_dfs_pulse;
-@@ -209,6 +216,11 @@ struct mt7996_phy {
+@@ -217,6 +224,11 @@ struct mt7996_phy {
  
  	struct ieee80211_vif *monitor_vif;
  
@@ -420,9 +420,9 @@
  	u32 rxfilter;
  	u64 omac_mask;
  
-@@ -457,6 +469,9 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
- int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+@@ -466,6 +478,9 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
  int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
+ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
  int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
 +int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
 +int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
@@ -431,5 +431,5 @@
  		       u8 rx_sel, u8 val);
  int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
similarity index 95%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
index 9e0668a..effc63b 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
@@ -1,7 +1,7 @@
-From 72f33a06b35ae981db88d12cd8db267ce68b9e08 Mon Sep 17 00:00:00 2001
+From db282c765c1d9cd2a5eec6a095069fd4bcf627b4 Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Thu, 2 Feb 2023 20:53:42 +0800
-Subject: [PATCH 08/22] wifi: mt76: mt7996: add thermal sensor device support
+Subject: [PATCH 18/39] wifi: mt76: mt7996: add thermal sensor device support
 
 ---
  mt7996/init.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -9,7 +9,7 @@
  2 files changed, 128 insertions(+)
 
 diff --git a/mt7996/init.c b/mt7996/init.c
-index 53852ffc..9c5d20ad 100644
+index c072b09..0319e7f 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
 @@ -4,6 +4,8 @@
@@ -128,10 +128,10 @@
  }
  
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 325051bd..f3fd2fd4 100644
+index c308d86..349c20e 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -3209,6 +3209,47 @@ out:
+@@ -3248,6 +3248,47 @@ out:
  	return 0;
  }
  
@@ -180,5 +180,5 @@
  int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
  {
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
similarity index 75%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
index b2ed6a1..1fef46a 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch
@@ -1,7 +1,7 @@
-From 854db11781bd8f9fa7cb45ed529223a4784de9d9 Mon Sep 17 00:00:00 2001
+From 2fe477b8db9ab494a975a565a28e35fff76505d1 Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Thu, 16 Mar 2023 16:09:51 +0800
-Subject: [PATCH 13/22] wifi: mt76: mt7996: fix beamform mcu cmd configuration
+Subject: [PATCH 19/39] wifi: mt76: mt7996: fix beamform mcu cmd configuration
 
 bf_num means how many band can support beamform, so the value shall be 3.
 bf_bitmap represents which band can support beamform.
@@ -10,10 +10,10 @@
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 6d11bc1a..df1ae639 100644
+index 349c20e..62e4869 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -3394,8 +3394,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
+@@ -3444,8 +3444,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
  
  		tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en));
  		req_mod_en = (struct bf_mod_en_ctrl *)tlv;
@@ -25,5 +25,5 @@
  	}
  	default:
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
similarity index 87%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
index 1e2ec3b..14855c7 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch
@@ -1,21 +1,26 @@
-From c1d0d0a15d4cdafa1ed0a61606fd5fefa85a6bb7 Mon Sep 17 00:00:00 2001
+From bfb2498bbef4bcfd44658fad8acf82730c56ede6 Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Tue, 20 Dec 2022 09:47:31 +0800
-Subject: [PATCH 15/22] wifi: mt76: mt7996: support more options in
+Subject: [PATCH] wifi: mt76: mt7996: support more options in
  .set_bitrate_mask()
 
 With this patch, driver can support runtime configuration for single
 rate, (HE)GI and HE_Ltf through .set_bitrate_mask(). Please noted that
 currently we do not support to fix any single parameter for EHT mode.
+
+Co-developed-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+Co-developed-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
 ---
- mt7996/mcu.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 137 insertions(+), 2 deletions(-)
+ mt7996/mcu.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 135 insertions(+), 2 deletions(-)
 
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index cd86209b..8a7487ba 100644
+index 62e4869..b7f378a 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1610,6 +1610,136 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
+@@ -1656,6 +1656,134 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
  				     MCU_WM_UNI_CMD(RA), true);
  }
  
@@ -75,10 +80,8 @@
 +	do {									\
 +		u8 i, gi = mask->control[band]._gi;				\
 +		gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI;		\
-+		for (i = 0; i <= sta->deflink.bandwidth; i++) {			\
-+			phy.sgi |= gi << (i << (_he));				\
-+			phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\
-+		}								\
++		phy.sgi = gi;							\
++		phy.he_ltf = mask->control[band].he_ltf;			\
 +		for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) {	\
 +			if (!mask->control[band]._mcs[i])			\
 +				continue;					\
@@ -152,7 +155,7 @@
  static void
  mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
  			     struct ieee80211_vif *vif, struct ieee80211_sta *sta)
-@@ -1719,6 +1849,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -1765,6 +1893,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
  	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
  	struct sk_buff *skb;
@@ -160,7 +163,7 @@
  
  	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
  					      &msta->wcid,
-@@ -1738,8 +1869,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -1784,8 +1913,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  	 */
  	mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
  
@@ -176,5 +179,5 @@
  
  static int
 -- 
-2.39.2
+2.39.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0021-mt76-testmode-add-chainmask-hacking-for-eagle-band-2.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0021-mt76-testmode-add-chainmask-hacking-for-eagle-band-2.patch
deleted file mode 100644
index a3a0633..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0021-mt76-testmode-add-chainmask-hacking-for-eagle-band-2.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 59c4b77798c213a1766b3dac36a9de08145f063e Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Thu, 9 Mar 2023 18:45:04 +0800
-Subject: [PATCH 21/22] mt76: testmode: add chainmask hacking for eagle band 2
- 4T5R
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- mt7996/testmode.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mt7996/testmode.c b/mt7996/testmode.c
-index 6d7cdbd5..0d4d9138 100644
---- a/mt7996/testmode.c
-+++ b/mt7996/testmode.c
-@@ -463,6 +463,7 @@ mt7996_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
- 		return 0;
- 
- 	chainmask = chainmask >> dev->chainshift[band_idx];
-+	chainmask = 0x1f;	/* hacking for eagle band2 4T5R */
- 	if (td->tx_antenna_mask > chainmask)
- 		return -EINVAL;
- 
--- 
-2.39.2
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-update-wmm-queue-mapping.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
similarity index 83%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
index 659e580..6b1d684 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch
@@ -1,7 +1,7 @@
-From c3611ca1b4d8260dee8893cb922ad2ad0a8eb8d7 Mon Sep 17 00:00:00 2001
+From 88577bcf928a15c2e8e78b7684ccb75dfc693eac Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Mon, 20 Mar 2023 19:09:59 +0800
-Subject: [PATCH 17/22] wifi: mt76: mt7996: update wmm queue mapping
+Subject: [PATCH 21/39] wifi: mt76: mt7996: update wmm queue mapping
 
 The mac80211 use mac80211 queue (MQ) and the firmware
 use access class index (ACI) so convert the MQ to ACI
@@ -14,7 +14,7 @@
  2 files changed, 10 insertions(+), 3 deletions(-)
 
 diff --git a/mt7996/main.c b/mt7996/main.c
-index fbb7270d..059cc420 100644
+index 9c80839..8e38ebc 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
 @@ -198,7 +198,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
@@ -26,7 +26,7 @@
  
  	ret = mt7996_mcu_add_dev_info(phy, vif, true);
  	if (ret)
-@@ -423,9 +423,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -422,9 +422,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  	       const struct ieee80211_tx_queue_params *params)
  {
  	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
@@ -45,10 +45,10 @@
  
  	return 0;
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 8a7487ba..43a4f939 100644
+index b27b88c..4359ede 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -2789,7 +2789,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
+@@ -2835,7 +2835,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
  
  		e = (struct edca *)tlv;
  		e->set = WMM_PARAM_SET;
@@ -58,5 +58,5 @@
  		e->txop = cpu_to_le16(q->txop);
  
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-enable-IDS-debug-log.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch
similarity index 84%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-enable-IDS-debug-log.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch
index ca2e812..659edd4 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-enable-IDS-debug-log.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch
@@ -1,14 +1,14 @@
-From 6e972b77bd615df709c8ce4401ea6e120ccdf758 Mon Sep 17 00:00:00 2001
+From 7e3ab3b90fc75ff41a503f4632a669c8cba2ae90 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Tue, 21 Mar 2023 15:04:45 +0800
-Subject: [PATCH 18/22] wifi: mt76: mt7996: enable IDS debug log
+Subject: [PATCH 22/39] wifi: mt76: mt7996: enable IDS debug log
 
 ---
  mt7996/debugfs.c | 10 ++++++++--
  1 file changed, 8 insertions(+), 2 deletions(-)
 
 diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 513ab4ba..04220180 100644
+index 513ab4b..0422018 100644
 --- a/mt7996/debugfs.c
 +++ b/mt7996/debugfs.c
 @@ -290,6 +290,12 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
@@ -36,5 +36,5 @@
  
  		if (debug == DEBUG_RPT_RX)
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-testmode-add-atenl-support-in-mt7996.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
similarity index 87%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-testmode-add-atenl-support-in-mt7996.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
index 1cbaf0e..686576d 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-testmode-add-atenl-support-in-mt7996.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch
@@ -1,7 +1,7 @@
-From e119dd8edebc8baa1e30945db3d0a7bc192bfc4b Mon Sep 17 00:00:00 2001
+From 33211d380fbf3b0892e560db99ac8dbc5c4e8cd5 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Wed, 28 Dec 2022 22:24:25 +0800
-Subject: [PATCH 19/22] mt76: testmode: add atenl support in mt7996
+Subject: [PATCH 23/39] wifi: mt76: testmode: add atenl support in mt7996
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
@@ -10,7 +10,7 @@
  2 files changed, 4 insertions(+), 1 deletion(-)
 
 diff --git a/testmode.c b/testmode.c
-index 0accc71a..0d2bae9f 100644
+index 0accc71..0d2bae9 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -612,7 +612,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
@@ -24,7 +24,7 @@
  
  	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
 diff --git a/testmode.h b/testmode.h
-index 5e2792d8..a40cd74b 100644
+index 5e2792d..a40cd74 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -17,6 +17,7 @@
@@ -44,5 +44,5 @@
  	MT76_TM_ATTR_TX_COUNT,
  	MT76_TM_ATTR_TX_LENGTH,
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0020-mt76-testmode-add-basic-testmode-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0020-mt76-testmode-add-basic-testmode-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch
index 30eef7a..6facdc3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0020-mt76-testmode-add-basic-testmode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0024-wifi-mt76-testmode-add-basic-testmode-support.patch
@@ -1,7 +1,7 @@
-From 058747d35c83a796712bec098cf6509965cf28cc Mon Sep 17 00:00:00 2001
+From 826ab7312fa42110844329a333df76dec614e48f Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Wed, 1 Mar 2023 11:59:16 +0800
-Subject: [PATCH 20/22] mt76: testmode: add basic testmode support
+Subject: [PATCH] wifi: mt76: testmode: add basic testmode support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
@@ -13,21 +13,21 @@
  mt7996/eeprom.c   |  35 ++-
  mt7996/eeprom.h   |   1 +
  mt7996/init.c     |   7 +
- mt7996/main.c     |  15 ++
- mt7996/mcu.c      |  39 ++-
+ mt7996/main.c     |  16 ++
+ mt7996/mcu.c      |  42 ++-
  mt7996/mcu.h      |  27 ++
  mt7996/mt7996.h   |  22 ++
- mt7996/testmode.c | 632 ++++++++++++++++++++++++++++++++++++++++++++++
- mt7996/testmode.h | 295 ++++++++++++++++++++++
- testmode.c        |  73 ++++--
+ mt7996/testmode.c | 658 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/testmode.h | 295 +++++++++++++++++++++
+ testmode.c        |  73 +++--
  testmode.h        |  60 +++++
  tools/fields.c    |  92 +++++++
- 17 files changed, 1315 insertions(+), 29 deletions(-)
+ 17 files changed, 1344 insertions(+), 30 deletions(-)
  create mode 100644 mt7996/testmode.c
  create mode 100644 mt7996/testmode.h
 
 diff --git a/eeprom.c b/eeprom.c
-index ea54b7af..263e5089 100644
+index ea54b7a..263e508 100644
 --- a/eeprom.c
 +++ b/eeprom.c
 @@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
@@ -44,7 +44,7 @@
  
  out_put_node:
 diff --git a/mac80211.c b/mac80211.c
-index 467afef9..d1cdaee8 100644
+index 467afef..d1cdaee 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -826,7 +826,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
@@ -58,7 +58,7 @@
  		if (status->flag & RX_FLAG_FAILED_FCS_CRC)
  			phy->test.rx_stats.fcs_error[q]++;
 diff --git a/mt76.h b/mt76.h
-index 6b07b8fa..31d5dc37 100644
+index 6b07b8f..31d5dc3 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -652,8 +652,12 @@ struct mt76_testmode_ops {
@@ -133,7 +133,7 @@
  {
  #ifdef CONFIG_NL80211_TESTMODE
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index fbb1206f..17cb8128 100644
+index 30c9a5d..724a48a 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -1218,10 +1218,12 @@ enum {
@@ -150,7 +150,7 @@
  	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
  	MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
 diff --git a/mt7996/Makefile b/mt7996/Makefile
-index 07c8b555..bed9efd6 100644
+index 07c8b55..bed9efd 100644
 --- a/mt7996/Makefile
 +++ b/mt7996/Makefile
 @@ -6,3 +6,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
@@ -160,7 +160,7 @@
 +
 +mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 544b6c6f..f5e95460 100644
+index 544b6c6..f5e9546 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
 @@ -6,6 +6,11 @@
@@ -230,7 +230,7 @@
  		if (ret < 0)
  			return ret;
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 0c749774..0f8f0cd8 100644
+index 0c74977..0f8f0cd 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
 @@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
@@ -242,10 +242,10 @@
  	MT_EE_RATE_DELTA_2G =	0x1400,
  	MT_EE_RATE_DELTA_5G =	0x147d,
 diff --git a/mt7996/init.c b/mt7996/init.c
-index d44e3ae9..36ead6db 100644
+index 0319e7f..fecd0d3 100644
 --- a/mt7996/init.c
 +++ b/mt7996/init.c
-@@ -639,6 +639,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+@@ -641,6 +641,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
  
  	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
  
@@ -256,7 +256,7 @@
  	ret = mt7996_mcu_init(dev);
  	if (ret)
  		return ret;
-@@ -1054,6 +1058,9 @@ int mt7996_register_device(struct mt7996_dev *dev)
+@@ -1056,6 +1060,9 @@ int mt7996_register_device(struct mt7996_dev *dev)
  
  	mt7996_init_wiphy(hw);
  
@@ -267,10 +267,10 @@
  	if (IS_ENABLED(CONFIG_MT76_LEDS)) {
  		dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
 diff --git a/mt7996/main.c b/mt7996/main.c
-index 059cc420..3820b235 100644
+index 8e38ebc..6c38993 100644
 --- a/mt7996/main.c
 +++ b/mt7996/main.c
-@@ -23,6 +23,17 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
+@@ -23,6 +23,18 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
  	return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
  }
  
@@ -281,14 +281,15 @@
 +
 +	for (i = 0; i < __MT_MAX_BAND; i++) {
 +		phy = __mt7996_phy(dev, i);
-+		mt76_testmode_set_state(phy->mt76, MT76_TM_STATE_OFF);
++		if (phy)
++			mt76_testmode_set_state(phy->mt76, MT76_TM_STATE_OFF);
 +	}
 +}
 +
  int mt7996_run(struct ieee80211_hw *hw)
  {
  	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-@@ -37,6 +48,8 @@ int mt7996_run(struct ieee80211_hw *hw)
+@@ -37,6 +49,8 @@ int mt7996_run(struct ieee80211_hw *hw)
  			goto out;
  	}
  
@@ -297,7 +298,7 @@
  	mt7996_mac_enable_nf(dev, phy->mt76->band_idx);
  
  	ret = mt7996_mcu_set_rts_thresh(phy, 0x92b);
-@@ -1390,6 +1403,8 @@ const struct ieee80211_ops mt7996_ops = {
+@@ -1389,6 +1403,8 @@ const struct ieee80211_ops mt7996_ops = {
  	.sta_set_decap_offload = mt7996_sta_set_decap_offload,
  	.add_twt_setup = mt7996_mac_add_twt_setup,
  	.twt_teardown_request = mt7996_twt_teardown_request,
@@ -307,22 +308,25 @@
  	.sta_add_debugfs = mt7996_sta_add_debugfs,
  #endif
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 43a4f939..24adeb12 100644
+index 665457a..0d2053c 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -2467,7 +2467,10 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
- 		release_firmware(fw);						\
- 	} while (0)
+@@ -2515,8 +2515,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+ {
+ 	int ret;
  
--	LOAD_RAM(WM);
+-	ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
+-				MT7996_RAM_TYPE_WM);
 +	if (dev->testmode_enable)
-+		LOAD_RAM(WM_TM);
++		ret = __mt7996_load_ram(dev, "WM_TM", MT7996_FIRMWARE_WM_TM,
++					MT7996_RAM_TYPE_WM_TM);
 +	else
-+		LOAD_RAM(WM);
- 	LOAD_RAM(DSP);
- 	LOAD_RAM(WA);
- #undef LOAD_RAM
-@@ -4012,3 +4015,37 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
++		ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
++					MT7996_RAM_TYPE_WM);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -4066,3 +4070,37 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
  	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
  				 sizeof(req), true);
  }
@@ -361,10 +365,10 @@
 +				 &req, sizeof(req), false);
 +}
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index 778deedf..ebc62713 100644
+index f235175..4ba06d9 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -686,6 +686,33 @@ enum {
+@@ -703,6 +703,33 @@ enum {
  	UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
  };
  
@@ -399,10 +403,10 @@
  	UNI_CMD_ACCESS_REG_BASIC = 0x0,
  	UNI_CMD_ACCESS_RF_REG_BASIC,
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index ab4521a4..9bf3bf1a 100644
+index 071031b..f7d6580 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -30,9 +30,11 @@
+@@ -31,9 +31,11 @@
  #define MT7996_FIRMWARE_WA		"mediatek/mt7996/mt7996_wa.bin"
  #define MT7996_FIRMWARE_WM		"mediatek/mt7996/mt7996_wm.bin"
  #define MT7996_FIRMWARE_DSP		"mediatek/mt7996/mt7996_dsp.bin"
@@ -413,16 +417,16 @@
 +#define MT7996_EEPROM_DEFAULT_TM	"mediatek/mt7996/mt7996_eeprom_tm.bin"
  #define MT7996_EEPROM_SIZE		7680
  #define MT7996_EEPROM_BLOCK_SIZE	16
- #define MT7996_TOKEN_SIZE		8192
-@@ -62,6 +64,7 @@ struct mt7996_dfs_pattern;
+ #define MT7996_TOKEN_SIZE		16384
+@@ -63,6 +65,7 @@ struct mt7996_dfs_pattern;
  
  enum mt7996_ram_type {
- 	MT7996_RAM_TYPE_WM = 0,
+ 	MT7996_RAM_TYPE_WM,
 +	MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
  	MT7996_RAM_TYPE_WA,
  	MT7996_RAM_TYPE_DSP,
  };
-@@ -243,6 +246,20 @@ struct mt7996_phy {
+@@ -244,6 +247,20 @@ struct mt7996_phy {
  
  	struct mib_stats mib;
  	struct mt76_channel_state state_ts;
@@ -443,7 +447,7 @@
  };
  
  struct mt7996_dev {
-@@ -302,6 +319,8 @@ struct mt7996_dev {
+@@ -303,6 +320,8 @@ struct mt7996_dev {
  	bool flash_mode:1;
  	bool has_eht:1;
  
@@ -452,7 +456,7 @@
  	bool ibf;
  	u8 fw_debug_wm;
  	u8 fw_debug_wa;
-@@ -407,6 +426,7 @@ mt7996_phy3(struct mt7996_dev *dev)
+@@ -408,6 +427,7 @@ mt7996_phy3(struct mt7996_dev *dev)
  extern const struct ieee80211_ops mt7996_ops;
  extern struct pci_driver mt7996_pci_driver;
  extern struct pci_driver mt7996_hif_driver;
@@ -460,7 +464,7 @@
  
  struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
  				     void __iomem *mem_base, u32 device_id);
-@@ -416,6 +436,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+@@ -417,6 +437,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
  int mt7996_register_device(struct mt7996_dev *dev);
  void mt7996_unregister_device(struct mt7996_dev *dev);
  int mt7996_eeprom_init(struct mt7996_dev *dev);
@@ -468,7 +472,7 @@
  int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
  int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
  				   struct ieee80211_channel *chan);
-@@ -492,6 +513,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
+@@ -494,6 +515,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
  int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
  void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
  void mt7996_mcu_exit(struct mt7996_dev *dev);
@@ -478,10 +482,10 @@
  {
 diff --git a/mt7996/testmode.c b/mt7996/testmode.c
 new file mode 100644
-index 00000000..6d7cdbd5
+index 0000000..43eca4e
 --- /dev/null
 +++ b/mt7996/testmode.c
-@@ -0,0 +1,632 @@
+@@ -0,0 +1,658 @@
 +// SPDX-License-Identifier: ISC
 +/*
 + * Copyright (C) 2022 MediaTek Inc.
@@ -554,6 +558,27 @@
 +}
 +
 +static int
++mt7996_tm_check_antenna(struct mt7996_phy *phy)
++{
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct mt7996_dev *dev = phy->dev;
++	u8 band_idx = phy->mt76->band_idx;
++	u32 chainmask = phy->mt76->chainmask;
++	u32 aux_rx_mask;
++
++	chainmask = chainmask >> dev->chainshift[band_idx];
++	aux_rx_mask = BIT(fls(chainmask)) * phy->has_aux_rx;
++	if (td->tx_antenna_mask & ~(chainmask | aux_rx_mask)) {
++		dev_err(dev->mt76.dev,
++			"tx antenna mask 0x%x exceeds hw limit (chainmask 0x%x, has aux rx: %s)\n",
++			td->tx_antenna_mask, chainmask, phy->has_aux_rx ? "yes" : "no");
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int
 +mt7996_tm_set(struct mt7996_dev *dev, u32 func_idx, u32 data)
 +{
 +	struct mt7996_tm_req req = {
@@ -603,6 +628,7 @@
 +mt7996_tm_set_antenna(struct mt7996_phy *phy, u32 func_idx)
 +{
 +#define SPE_INDEX_MASK		BIT(31)
++#define TX_ANTENNA_MASK		GENMASK(3, 0)
 +#define RX_ANTENNA_MASK		GENMASK(20, 16)		/* RX antenna mask at most 5 bit */
 +	struct mt7996_dev *dev = phy->dev;
 +	struct mt76_testmode_data *td = &phy->mt76->test;
@@ -613,7 +639,7 @@
 +
 +	if (func_idx == SET_ID(TX_PATH))
 +		antenna_mask = td->tx_spe_idx ? (SPE_INDEX_MASK | td->tx_spe_idx) :
-+						td->tx_antenna_mask;
++						td->tx_antenna_mask & TX_ANTENNA_MASK;
 +	else if (func_idx == SET_ID(RX_PATH))
 +		antenna_mask = u32_encode_bits(td->tx_antenna_mask, RX_ANTENNA_MASK);
 +	else
@@ -758,6 +784,7 @@
 +		}
 +
 +		mt7996_tm_set_antenna(phy, SET_ID(TX_PATH));
++		mt7996_tm_set_antenna(phy, SET_ID(RX_PATH));
 +		mt7996_tm_set(dev, SET_ID(STBC), td->tx_rate_stbc);
 +		mt7996_tm_set(dev, SET_ID(ENCODE_MODE), td->tx_rate_ldpc);
 +		mt7996_tm_set(dev, SET_ID(IBF_ENABLE), td->ibf);
@@ -914,7 +941,7 @@
 +	    (state == MT76_TM_STATE_OFF &&
 +	     prev_state == MT76_TM_STATE_IDLE)) {
 +		u32 changed = 0;
-+		int i;
++		int i, ret;
 +
 +		for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
 +			u16 cur = tm_change_map[i];
@@ -923,6 +950,10 @@
 +				changed |= BIT(i);
 +		}
 +
++		ret = mt7996_tm_check_antenna(phy);
++		if (ret)
++			return ret;
++
 +		mt7996_tm_update_params(phy, changed);
 +	}
 +
@@ -936,9 +967,8 @@
 +	struct mt76_testmode_data *td = &mphy->test;
 +	struct mt7996_phy *phy = mphy->priv;
 +	struct mt7996_dev *dev = phy->dev;
-+	u32 chainmask = mphy->chainmask, changed = 0;
-+	u8 band_idx = phy->mt76->band_idx;
-+	int i;
++	u32 changed = 0;
++	int i, ret;
 +
 +	BUILD_BUG_ON(NUM_TM_CHANGED >= 32);
 +
@@ -946,9 +976,9 @@
 +	    td->state == MT76_TM_STATE_OFF)
 +		return 0;
 +
-+	chainmask = chainmask >> dev->chainshift[band_idx];
-+	if (td->tx_antenna_mask > chainmask)
-+		return -EINVAL;
++	ret = mt7996_tm_check_antenna(phy);
++	if (ret)
++		return ret;
 +
 +	for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
 +		if (tb[tm_change_map[i]])
@@ -1116,7 +1146,7 @@
 +};
 diff --git a/mt7996/testmode.h b/mt7996/testmode.h
 new file mode 100644
-index 00000000..f00e51f4
+index 0000000..f00e51f
 --- /dev/null
 +++ b/mt7996/testmode.h
 @@ -0,0 +1,295 @@
@@ -1416,7 +1446,7 @@
 +
 +#endif
 diff --git a/testmode.c b/testmode.c
-index 0d2bae9f..fc68c2af 100644
+index 0d2bae9..fc68c2a 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -2,6 +2,7 @@
@@ -1590,7 +1620,7 @@
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
 diff --git a/testmode.h b/testmode.h
-index a40cd74b..8d0b9702 100644
+index a40cd74..8d0b970 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -39,6 +39,11 @@
@@ -1710,7 +1740,7 @@
  	/* keep last */
  	NUM_MT76_TM_TX_MODES,
 diff --git a/tools/fields.c b/tools/fields.c
-index e3f69089..e5cf7c53 100644
+index e3f6908..e5cf7c5 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -1872,5 +1902,5 @@
  
  const struct tm_field msg_field = {
 -- 
-2.39.2
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch
new file mode 100644
index 0000000..06e273a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0026-wifi-mt76-mt7996-add-led-feature-support.patch
@@ -0,0 +1,105 @@
+From 030159528eff349db01b6b47b6fff8112b4282a4 Mon Sep 17 00:00:00 2001
+From: mtk25577 <jen-hao.cheng@mediatek.com>
+Date: Tue, 28 Mar 2023 18:23:00 +0800
+Subject: [PATCH 26/39] wifi: mt76: mt7996: add led feature support
+
+Signed-off-by: mtk25577 <jen-hao.cheng@mediatek.com>
+---
+ mt7996/Makefile |  1 +
+ mt7996/init.c   | 33 +++++++++++++++++++++------------
+ mt7996/regs.h   |  1 +
+ 3 files changed, 23 insertions(+), 12 deletions(-)
+
+diff --git a/mt7996/Makefile b/mt7996/Makefile
+index bed9efd..7c2514a 100644
+--- a/mt7996/Makefile
++++ b/mt7996/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: ISC
++EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
+ 
+ obj-$(CONFIG_MT7996E) += mt7996e.o
+ 
+diff --git a/mt7996/init.c b/mt7996/init.c
+index fecd0d3..192af3f 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -232,23 +232,31 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev,
+ 	dev = container_of(mphy->dev, struct mt7996_dev, mt76);
+ 
+ 	/* select TX blink mode, 2: only data frames */
+-	mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2);
++	mt76_rmw_field(dev, MT_TMAC_TCR0(mphy->band_idx), MT_TMAC_TCR0_TX_BLINK, 2);
+ 
+ 	/* enable LED */
+-	mt76_wr(dev, MT_LED_EN(0), 1);
++	mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);
+ 
+ 	/* set LED Tx blink on/off time */
+ 	val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) |
+ 	      FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off);
+-	mt76_wr(dev, MT_LED_TX_BLINK(0), val);
++	mt76_wr(dev, MT_LED_TX_BLINK(mphy->band_idx), val);
++
++	/* turn LED off */
++	if (delay_off == 0xff && delay_on == 0x0)
++		val = MT_LED_CTRL_POLARITY | MT_LED_CTRL_KICK;
++	else {
++		/* control LED */
++		val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
++		if (mphy->band_idx == MT_BAND1)
++			val |= MT_LED_CTRL_BLINK_BAND_SEL;
++	}
+ 
+-	/* control LED */
+-	val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
+ 	if (mphy->leds.al)
+ 		val |= MT_LED_CTRL_POLARITY;
+ 
+-	mt76_wr(dev, MT_LED_CTRL(0), val);
+-	mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK);
++	mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);
++	mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);
+ }
+ 
+ static int mt7996_led_set_blink(struct led_classdev *led_cdev,
+@@ -400,6 +408,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 		ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
+ 	}
+ 
++	/* init led callbacks */
++	if (IS_ENABLED(CONFIG_MT76_LEDS)) {
++		phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness;
++		phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink;
++	}
++
+ 	mt76_set_stream_caps(phy->mt76, true);
+ 	mt7996_set_stream_vht_txbf_caps(phy);
+ 	mt7996_set_stream_he_eht_caps(phy);
+@@ -1063,11 +1077,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ #ifdef CONFIG_NL80211_TESTMODE
+ 	dev->mt76.test_ops = &mt7996_testmode_ops;
+ #endif
+-	/* init led callbacks */
+-	if (IS_ENABLED(CONFIG_MT76_LEDS)) {
+-		dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
+-		dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink;
+-	}
+ 
+ 	ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+ 				   ARRAY_SIZE(mt76_rates));
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index d1d3d15..86da1bf 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -509,6 +509,7 @@ enum base_rev {
+ 
+ #define MT_LED_CTRL(_n)				MT_LED_PHYS(0x00 + ((_n) * 4))
+ #define MT_LED_CTRL_KICK			BIT(7)
++#define MT_LED_CTRL_BLINK_BAND_SEL		BIT(4)
+ #define MT_LED_CTRL_BLINK_MODE			BIT(2)
+ #define MT_LED_CTRL_POLARITY			BIT(1)
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch
new file mode 100644
index 0000000..2e938b7
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch
@@ -0,0 +1,60 @@
+From e503dbe84bc2b46907a792e11c196018b274647a Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Tue, 28 Mar 2023 20:20:57 +0800
+Subject: [PATCH 27/39] wifi: mt76: mt7996: fix twt mcu command
+
+Update unified command for twt.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7915/mcu.h | 1 -
+ mt7996/mcu.c | 7 +++++--
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index b9ea297..e7a5395 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -264,7 +264,6 @@ enum {
+ 	MCU_TWT_AGRT_MODIFY,
+ 	MCU_TWT_AGRT_DELETE,
+ 	MCU_TWT_AGRT_TEARDOWN,
+-	MCU_TWT_AGRT_GET_TSF,
+ };
+ 
+ enum {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a6d8235..6bcb33e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3823,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ 			       int cmd)
+ {
+ 	struct {
+-		u8 _rsv[4];
++		/* fixed field */
++		u8 bss;
++		u8 _rsv[3];
+ 
+ 		__le16 tag;
+ 		__le16 len;
+@@ -3841,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ 		u8 exponent;
+ 		u8 is_ap;
+ 		u8 agrt_params;
+-		u8 __rsv2[135];
++		u8 __rsv2[23];
+ 	} __packed req = {
+ 		.tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE),
+ 		.len = cpu_to_le16(sizeof(req) - 4),
+@@ -3851,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ 		.flowid = flow->id,
+ 		.peer_id = cpu_to_le16(flow->wcid),
+ 		.duration = flow->duration,
++		.bss = mvif->mt76.idx,
+ 		.bss_idx = mvif->mt76.idx,
+ 		.start_tsf = cpu_to_le64(flow->tsf),
+ 		.mantissa = flow->mantissa,
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch
new file mode 100644
index 0000000..bf724c8
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch
@@ -0,0 +1,181 @@
+From 0449694e4e963d0b48354ae2c52016c34899fba6 Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Wed, 8 Mar 2023 14:18:29 +0800
+Subject: [PATCH 28/39] wifi: mt76: mt7996: add 11v mbss support for mt76
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ mt76_connac_mcu.h | 10 ++++++
+ mt7996/init.c     |  2 ++
+ mt7996/mcu.c      | 79 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 90 insertions(+), 1 deletion(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 724a48a..97f874b 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1281,6 +1281,7 @@ enum {
+ 	UNI_BSS_INFO_RLM = 2,
+ 	UNI_BSS_INFO_BSS_COLOR = 4,
+ 	UNI_BSS_INFO_HE_BASIC = 5,
++	UNI_BSS_INFO_11V_MBSSID = 6,
+ 	UNI_BSS_INFO_BCN_CONTENT = 7,
+ 	UNI_BSS_INFO_BCN_CSA = 8,
+ 	UNI_BSS_INFO_BCN_BCC = 9,
+@@ -1551,6 +1552,15 @@ struct bss_info_uni_he {
+ 	u8 rsv[2];
+ } __packed;
+ 
++struct bss_info_uni_mbssid {
++	__le16 tag;
++	__le16 len;
++	u8 max_indicator;
++	u8 mbss_idx;
++	u8 tx_bss_omac_idx;
++	u8 rsv[1];
++} __packed;
++
+ struct mt76_connac_gtk_rekey_tlv {
+ 	__le16 tag;
+ 	__le16 len;
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 192af3f..0562439 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -359,6 +359,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+ 	wiphy->reg_notifier = mt7996_regd_notifier;
+ 	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
++	wiphy->mbssid_max_interfaces = 16;
+ 
+ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
+ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+@@ -381,6 +382,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 	ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
+ 	ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
+ 	ieee80211_hw_set(hw, WANT_MONITOR_VIF);
++	ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
+ 
+ 	hw->max_tx_fragments = 4;
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6bcb33e..a369a08 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -631,6 +631,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ 	he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
+ }
+ 
++static void
++mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
++		      struct mt7996_phy *phy)
++{
++	struct bss_info_uni_mbssid *mbssid;
++	struct tlv *tlv;
++
++	tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid));
++
++	mbssid = (struct bss_info_uni_mbssid *)tlv;
++
++	mbssid->max_indicator = vif->bss_conf.bssid_indicator;
++	mbssid->mbss_idx = vif->bss_conf.bssid_index;
++	mbssid->tx_bss_omac_idx = 0;
++
++	return;
++}
++
+ static void
+ mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ 		       struct mt7996_phy *phy)
+@@ -895,6 +913,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
+ 		if (vif->bss_conf.he_support)
+ 			mt7996_mcu_bss_he_tlv(skb, vif, phy);
+ 
++		if (vif->bss_conf.bssid_indicator)
++			mt7996_mcu_bss_mbssid_tlv(skb, vif, phy);
++
+ 		/* this tag is necessary no matter if the vif is MLD */
+ 		mt7996_mcu_bss_mld_tlv(skb, vif);
+ 	}
+@@ -2162,6 +2183,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
+ 	info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
+ }
+ 
++static void
++mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
++			struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn,
++			struct ieee80211_mutable_offsets *offs)
++{
++	struct bss_bcn_mbss_tlv *mbss;
++	const struct element *elem;
++	struct tlv *tlv;
++
++	if (!vif->bss_conf.bssid_indicator)
++		return;
++
++	tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss));
++
++	mbss = (struct bss_bcn_mbss_tlv *)tlv;
++	mbss->offset[0] = cpu_to_le16(offs->tim_offset);
++	mbss->bitmap = cpu_to_le32(1);
++
++	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
++			&skb->data[offs->mbssid_off],
++			skb->len - offs->mbssid_off) {
++		const struct element *sub_elem;
++
++		if (elem->datalen < 2)
++			continue;
++
++		for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
++			const struct ieee80211_bssid_index *idx;
++			const u8 *idx_ie;
++
++			if (sub_elem->id || sub_elem->datalen < 4)
++				 continue; /* not a valid BSS profile */
++
++			/* Find WLAN_EID_MULTI_BSSID_IDX
++			 * in the merged nontransmitted profile
++			 */
++			idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
++						sub_elem->data,
++						sub_elem->datalen);
++			if (!idx_ie || idx_ie[1] < sizeof(*idx))
++				 continue;
++
++			idx = (void *)(idx_ie + 2);
++			if (!idx->bssid_index || idx->bssid_index > 31)
++				continue;
++
++			mbss->offset[idx->bssid_index] =
++				cpu_to_le16(idx_ie - skb->data);
++			mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
++		}
++	}
++}
++
+ static void
+ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ 		       struct sk_buff *rskb, struct sk_buff *skb,
+@@ -2202,6 +2276,9 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
+ 	struct tlv *tlv;
+ 	struct bss_bcn_content_tlv *bcn;
+ 
++	if (vif->bss_conf.nontransmitted)
++		return 0;
++
+ 	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
+ 					  MT7996_BEACON_UPDATE_SIZE);
+ 	if (IS_ERR(rskb))
+@@ -2229,7 +2306,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
+ 	info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
+ 
+ 	mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
+-	/* TODO: subtag - 11v MBSSID */
++	mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
+ 	mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
+ 	dev_kfree_skb(skb);
+ out:
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch
new file mode 100644
index 0000000..67e5c6c
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch
@@ -0,0 +1,188 @@
+From 8b591f425b1bb71ebde4a1eb9c926f0c9017fe28 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Mon, 27 Mar 2023 09:47:44 +0800
+Subject: [PATCH 29/39] wifi: mt76: mt7996: Update beacon size limitation for
+ 11v
+
+The TLV size limitation for these two has been expanded to
+accommodate 11v MBSSID IE.
+
+Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Co-developed-by: Money Wang <Money.Wang@mediatek.com>
+Signed-off-by: Money Wang <Money.Wang@mediatek.com>
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ mt7996/main.c |  4 ++--
+ mt7996/mcu.c  | 39 +++++++++++++++++++++++----------------
+ mt7996/mcu.h  | 11 ++++-------
+ 3 files changed, 29 insertions(+), 25 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 6c38993..520f250 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -618,8 +618,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ 		mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
+ 	}
+ 
+-	if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
+-	    changed & BSS_CHANGED_FILS_DISCOVERY)
++	if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
++		       BSS_CHANGED_FILS_DISCOVERY))
+ 		mt7996_mcu_beacon_inband_discov(dev, vif, changed);
+ 
+ 	mutex_unlock(&dev->mt76.mutex);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a369a08..7b8f883 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2257,7 +2257,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ 			bcn->bcc_ie_pos = cpu_to_le16(offset - 3);
+ 	}
+ 
+-	buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
++	buf = (u8 *)bcn + sizeof(*bcn);
+ 	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
+ 			      BSS_CHANGED_BEACON);
+ 
+@@ -2275,28 +2275,21 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
+ 	struct sk_buff *skb, *rskb;
+ 	struct tlv *tlv;
+ 	struct bss_bcn_content_tlv *bcn;
++	int len;
+ 
+ 	if (vif->bss_conf.nontransmitted)
+ 		return 0;
+ 
+ 	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
+-					  MT7996_BEACON_UPDATE_SIZE);
++					  MT7996_MAX_BSS_OFFLOAD_SIZE);
+ 	if (IS_ERR(rskb))
+ 		return PTR_ERR(rskb);
+ 
+-	tlv = mt7996_mcu_add_uni_tlv(rskb,
+-				     UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn));
+-	bcn = (struct bss_bcn_content_tlv *)tlv;
+-	bcn->enable = en;
+-
+-	if (!en)
+-		goto out;
+-
+ 	skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
+ 	if (!skb)
+ 		return -EINVAL;
+ 
+-	if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
++	if (skb->len > MT7996_MAX_BEACON_SIZE) {
+ 		dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
+ 		dev_kfree_skb(skb);
+ 		return -EINVAL;
+@@ -2305,11 +2298,19 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
+ 	info = IEEE80211_SKB_CB(skb);
+ 	info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
+ 
++	len = sizeof(*bcn) + MT_TXD_SIZE + skb->len;
++	tlv = mt7996_mcu_add_uni_tlv(rskb,
++				     UNI_BSS_INFO_BCN_CONTENT, len);
++	bcn = (struct bss_bcn_content_tlv *)tlv;
++	bcn->enable = en;
++	if (!en)
++		goto out;
++
+ 	mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
+ 	mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
+ 	mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
+-	dev_kfree_skb(skb);
+ out:
++	dev_kfree_skb(skb);
+ 	return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
+ 				     MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
+ }
+@@ -2330,9 +2331,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	struct sk_buff *rskb, *skb = NULL;
+ 	struct tlv *tlv;
+ 	u8 *buf, interval;
++	int len;
++
++	if (vif->bss_conf.nontransmitted)
++		return 0;
+ 
+ 	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
+-					  MT7996_INBAND_FRAME_SIZE);
++					  MT7996_MAX_BSS_OFFLOAD_SIZE);
+ 	if (IS_ERR(rskb))
+ 		return PTR_ERR(rskb);
+ 
+@@ -2349,7 +2354,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	if (!skb)
+ 		return -EINVAL;
+ 
+-	if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) {
++	if (skb->len > MT7996_MAX_BEACON_SIZE) {
+ 		dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
+ 		dev_kfree_skb(skb);
+ 		return -EINVAL;
+@@ -2360,7 +2365,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	info->band = band;
+ 	info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
+ 
+-	tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov));
++	len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
++
++	tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
+ 
+ 	discov = (struct bss_inband_discovery_tlv *)tlv;
+ 	discov->tx_mode = OFFLOAD_TX_MODE_SU;
+@@ -2371,7 +2378,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	discov->enable = true;
+ 	discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
+ 
+-	buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
++	buf = (u8 *)tlv + sizeof(*discov);
+ 
+ 	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
+ 
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 4ba06d9..eed7371 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -308,8 +308,6 @@ struct bss_inband_discovery_tlv {
+ 	u8 enable;
+ 	__le16 wcid;
+ 	__le16 prob_rsp_len;
+-#define MAX_INBAND_FRAME_SIZE 512
+-	u8 pkt[MAX_INBAND_FRAME_SIZE];
+ } __packed;
+ 
+ struct bss_bcn_content_tlv {
+@@ -321,8 +319,6 @@ struct bss_bcn_content_tlv {
+ 	u8 enable;
+ 	u8 type;
+ 	__le16 pkt_len;
+-#define MAX_BEACON_SIZE 512
+-	u8 pkt[MAX_BEACON_SIZE];
+ } __packed;
+ 
+ struct bss_bcn_cntdwn_tlv {
+@@ -629,13 +625,14 @@ enum {
+ 					 sizeof(struct sta_rec_hdr_trans) +	\
+ 					 sizeof(struct tlv))
+ 
++#define MT7996_MAX_BEACON_SIZE		1342
+ #define MT7996_BEACON_UPDATE_SIZE	(sizeof(struct bss_req_hdr) +		\
+ 					 sizeof(struct bss_bcn_content_tlv) +	\
++					 MT_TXD_SIZE +				\
+ 					 sizeof(struct bss_bcn_cntdwn_tlv) +	\
+ 					 sizeof(struct bss_bcn_mbss_tlv))
+-
+-#define MT7996_INBAND_FRAME_SIZE	(sizeof(struct bss_req_hdr) +		\
+-					 sizeof(struct bss_inband_discovery_tlv))
++#define MT7996_MAX_BSS_OFFLOAD_SIZE	(MT7996_MAX_BEACON_SIZE +		\
++					 MT7996_BEACON_UPDATE_SIZE)
+ 
+ enum {
+ 	UNI_BAND_CONFIG_RADIO_ENABLE,
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
new file mode 100644
index 0000000..798eb69
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch
@@ -0,0 +1,138 @@
+From 7390e5db3745febd580026e723b2ca806e308008 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Fri, 14 Apr 2023 16:51:59 +0800
+Subject: [PATCH 30/39] wifi: mt76: mt7996: add support for auxiliary path
+
+Add support to correctly configure the setting of variants that have
+additional TX or RX path.
+
+Change-Id: I1312c193beab5e16aae7161a7e3bdda100b72f8d
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/eeprom.c | 21 +++++++++++++++++----
+ mt7996/eeprom.h |  3 +++
+ mt7996/mcu.c    |  2 +-
+ mt7996/mt7996.h | 14 ++++++++++++++
+ 4 files changed, 35 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index f5e9546..9840c77 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -171,36 +171,49 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
+ 
+ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
+ {
+-	u8 path, nss, band_idx = phy->mt76->band_idx;
++	u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;
+ 	u8 *eeprom = dev->mt76.eeprom.data;
+ 	struct mt76_phy *mphy = phy->mt76;
++	int max_path = 5, max_nss = 4;
+ 	int ret;
+ 
+ 	switch (band_idx) {
+ 	case MT_BAND1:
+ 		path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,
+ 				 eeprom[MT_EE_WIFI_CONF + 2]);
++		rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,
++				    eeprom[MT_EE_WIFI_CONF + 3]);
+ 		nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,
+ 				eeprom[MT_EE_WIFI_CONF + 5]);
+ 		break;
+ 	case MT_BAND2:
+ 		path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,
+ 				 eeprom[MT_EE_WIFI_CONF + 2]);
++		rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,
++				    eeprom[MT_EE_WIFI_CONF + 4]);
+ 		nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,
+ 				eeprom[MT_EE_WIFI_CONF + 5]);
+ 		break;
+ 	default:
+ 		path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,
+ 				 eeprom[MT_EE_WIFI_CONF + 1]);
++		rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,
++				    eeprom[MT_EE_WIFI_CONF + 3]);
+ 		nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,
+ 				eeprom[MT_EE_WIFI_CONF + 4]);
+ 		break;
+ 	}
+ 
+-	if (!path || path > 4)
+-		path = 4;
++	if (!path || path > max_path)
++		path = max_path;
+ 
+-	nss = min_t(u8, min_t(u8, 4, nss), path);
++	if (!nss || nss > max_nss)
++		nss = max_nss;
++
++	nss = min_t(u8, nss, path);
++
++	if (path != rx_path)
++		phy->has_aux_rx = true;
+ 
+ 	mphy->antenna_mask = BIT(nss) - 1;
+ 	mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 0f8f0cd..9ea3667 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -34,6 +34,9 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CONF1_TX_PATH_BAND0		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF2_TX_PATH_BAND1		GENMASK(2, 0)
+ #define MT_EE_WIFI_CONF2_TX_PATH_BAND2		GENMASK(5, 3)
++#define MT_EE_WIFI_CONF3_RX_PATH_BAND0		GENMASK(2, 0)
++#define MT_EE_WIFI_CONF3_RX_PATH_BAND1		GENMASK(5, 3)
++#define MT_EE_WIFI_CONF4_RX_PATH_BAND2		GENMASK(2, 0)
+ #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0	GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1	GENMASK(2, 0)
+ #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2	GENMASK(5, 3)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 7b8f883..a2c1e43 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3198,7 +3198,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
+ 		.center_ch = ieee80211_frequency_to_channel(freq1),
+ 		.bw = mt76_connac_chan_bw(chandef),
+ 		.tx_path_num = hweight16(phy->mt76->chainmask),
+-		.rx_path = phy->mt76->chainmask >> dev->chainshift[band_idx],
++		.rx_path = mt7996_rx_chainmask(phy) >> dev->chainshift[band_idx],
+ 		.band_idx = band_idx,
+ 		.channel_band = ch_band[chandef->chan->band],
+ 	};
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index f7d6580..8e5b3c3 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -248,6 +248,8 @@ struct mt7996_phy {
+ 	struct mib_stats mib;
+ 	struct mt76_channel_state state_ts;
+ 
++	bool has_aux_rx;
++
+ #ifdef CONFIG_NL80211_TESTMODE
+ 	struct {
+ 		u32 *reg_backup;
+@@ -551,6 +553,18 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
+ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
+ 			  size_t len);
+ 
++static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
++{
++	int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx);
++	int cur_nss = hweight8(phy->mt76->antenna_mask);
++	u16 tx_chainmask = phy->mt76->chainmask;
++
++	if (cur_nss != max_nss)
++		return tx_chainmask;
++
++	return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
++}
++
+ void mt7996_mac_init(struct mt7996_dev *dev);
+ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
+ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch
new file mode 100644
index 0000000..0669836
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0031-wifi-mt76-mt7996-fix-memory-leak.patch
@@ -0,0 +1,49 @@
+From 80a4f15fa3077ef5a340a4af5b12fda8d958c337 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Tue, 18 Apr 2023 19:49:45 +0800
+Subject: [PATCH 31/39] wifi: mt76: mt7996: fix memory leak.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7996/mcu.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a2c1e43..f98a48d 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2286,11 +2286,14 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
+ 		return PTR_ERR(rskb);
+ 
+ 	skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
+-	if (!skb)
++	if (!skb) {
++		dev_kfree_skb(rskb);
+ 		return -EINVAL;
++	}
+ 
+ 	if (skb->len > MT7996_MAX_BEACON_SIZE) {
+ 		dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
++		dev_kfree_skb(rskb);
+ 		dev_kfree_skb(skb);
+ 		return -EINVAL;
+ 	}
+@@ -2351,11 +2354,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 		skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
+ 	}
+ 
+-	if (!skb)
++	if (!skb) {
++		dev_kfree_skb(rskb);
+ 		return -EINVAL;
++	}
+ 
+ 	if (skb->len > MT7996_MAX_BEACON_SIZE) {
+ 		dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
++		dev_kfree_skb(rskb);
+ 		dev_kfree_skb(skb);
+ 		return -EINVAL;
+ 	}
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
new file mode 100644
index 0000000..ba0e378
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch
@@ -0,0 +1,39 @@
+From fd7730026ccef8b0d5a52ac07ddb21af48def17d Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 20 Apr 2023 16:34:47 +0800
+Subject: [PATCH 32/39] wifi: mt76: mt7996: add eht mode tx stats
+
+Add eht mode bf fbk stats and bw320 through debugfs tx_stats command
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/debugfs.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 0422018..ca4d615 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -481,7 +481,7 @@ static void
+ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
+ {
+ 	static const char * const bw[] = {
+-		"BW20", "BW40", "BW80", "BW160"
++		"BW20", "BW40", "BW80", "BW160", "BW320"
+ 	};
+ 	struct mib_stats *mib = &phy->mib;
+ 
+@@ -495,8 +495,9 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
+ 	/* Tx Beamformer Rx feedback monitor */
+ 	seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
+ 
+-	seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",
++	seq_printf(s, "All: %d, EHT: %d, HE: %d, VHT: %d, HT: %d, ",
+ 		   mib->tx_bf_rx_fb_all_cnt,
++		   mib->tx_bf_rx_fb_eht_cnt,
+ 		   mib->tx_bf_rx_fb_he_cnt,
+ 		   mib->tx_bf_rx_fb_vht_cnt,
+ 		   mib->tx_bf_rx_fb_ht_cnt);
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch
new file mode 100644
index 0000000..a88d36a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch
@@ -0,0 +1,219 @@
+From d246d8300bcbf7dea19919d61df9d7553e21bd1b Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Wed, 26 Apr 2023 15:37:23 +0800
+Subject: [PATCH 33/39] wifi: mt76: mt7996: disable wfdma tx/rx during SER
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ dma.c           |  6 ++++
+ mt7996/dma.c    | 79 ++++++++++++++++++++++++++++++-------------------
+ mt7996/mac.c    | 13 ++++++--
+ mt7996/mt7996.h |  1 +
+ 4 files changed, 65 insertions(+), 34 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 465190e..f2b1b2a 100644
+--- a/dma.c
++++ b/dma.c
+@@ -466,6 +466,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+ 	struct mt76_queue_buf buf = {};
+ 	dma_addr_t addr;
+ 
++	if (test_bit(MT76_MCU_RESET, &dev->phy.state))
++		goto error;
++
+ 	if (q->queued + 1 >= q->ndesc - 1)
+ 		goto error;
+ 
+@@ -507,6 +510,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ 	dma_addr_t addr;
+ 	u8 *txwi;
+ 
++	if (test_bit(MT76_MCU_RESET, &dev->phy.state))
++		goto free_skb;
++
+ 	t = mt76_get_txwi(dev);
+ 	if (!t)
+ 		goto free_skb;
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index fbedaac..6a21e3e 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -128,11 +128,55 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
+ 	}
+ }
+ 
+-static int mt7996_dma_enable(struct mt7996_dev *dev)
++void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ {
+ 	u32 hif1_ofs = 0;
+ 	u32 irq_mask;
+ 
++	if (dev->hif2)
++		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++
++	/* enable wpdma tx/rx */
++	if (!reset) {
++		mt76_set(dev, MT_WFDMA0_GLO_CFG,
++			 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++			 MT_WFDMA0_GLO_CFG_RX_DMA_EN |
++			 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++			 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++
++		if (dev->hif2)
++			mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
++				 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++				 MT_WFDMA0_GLO_CFG_RX_DMA_EN |
++				 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++				 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++	}
++
++	/* enable interrupts for TX/RX rings */
++	irq_mask = MT_INT_MCU_CMD;
++	if (reset)
++		goto done;
++
++	irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
++
++	if (!dev->mphy.band_idx)
++		irq_mask |= MT_INT_BAND0_RX_DONE;
++
++	if (dev->dbdc_support)
++		irq_mask |= MT_INT_BAND1_RX_DONE;
++
++	if (dev->tbtc_support)
++		irq_mask |= MT_INT_BAND2_RX_DONE;
++
++done:
++	mt7996_irq_enable(dev, irq_mask);
++	mt7996_irq_disable(dev, 0);
++}
++
++static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
++{
++	u32 hif1_ofs = 0;
++
+ 	if (dev->hif2)
+ 		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+ 
+@@ -170,13 +214,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
+ 	mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC,
+ 		  MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000);
+ 
+-	/* set WFDMA Tx/Rx */
+-	mt76_set(dev, MT_WFDMA0_GLO_CFG,
+-		 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-		 MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+-		 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+-		 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+-
+ 	/* GLO_CFG_EXT0 */
+ 	mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0,
+ 		 WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
+@@ -187,12 +224,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
+ 		 WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
+ 
+ 	if (dev->hif2) {
+-		mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+-			 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-			 MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+-			 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+-			 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+-
+ 		/* GLO_CFG_EXT0 */
+ 		mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
+ 			 WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
+@@ -216,21 +247,7 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
+ 		/* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
+ 	}
+ 
+-	/* enable interrupts for TX/RX rings */
+-	irq_mask = MT_INT_RX_DONE_MCU |
+-		   MT_INT_TX_DONE_MCU |
+-		   MT_INT_MCU_CMD;
+-
+-	if (!dev->mphy.band_idx)
+-		irq_mask |= MT_INT_BAND0_RX_DONE;
+-
+-	if (dev->dbdc_support)
+-		irq_mask |= MT_INT_BAND1_RX_DONE;
+-
+-	if (dev->tbtc_support)
+-		irq_mask |= MT_INT_BAND2_RX_DONE;
+-
+-	mt7996_irq_enable(dev, irq_mask);
++	__mt7996_dma_enable(dev, reset);
+ 
+ 	return 0;
+ }
+@@ -347,7 +364,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 			  mt7996_poll_tx);
+ 	napi_enable(&dev->mt76.tx_napi);
+ 
+-	mt7996_dma_enable(dev);
++	mt7996_dma_enable(dev, false);
+ 
+ 	return 0;
+ }
+@@ -413,7 +430,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+ 	mt76_for_each_q_rx(&dev->mt76, i)
+ 		mt76_queue_rx_reset(dev, i);
+ 
+-	mt7996_dma_enable(dev);
++	mt7996_dma_enable(dev, !force);
+ }
+ 
+ void mt7996_dma_cleanup(struct mt7996_dev *dev)
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index bddb84f..986031f 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2028,6 +2028,12 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 		mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
+ 	}
+ 
++	mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
++	mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
++
++	/* enable dma tx/rx and interrupt */
++	__mt7996_dma_enable(dev, false);
++
+ 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	clear_bit(MT76_RESET, &dev->mphy.state);
+ 	if (phy2)
+@@ -2044,9 +2050,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 
+ 	tasklet_schedule(&dev->mt76.irq_tasklet);
+ 
+-	mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
+-	mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
+-
+ 	mt76_worker_enable(&dev->mt76.tx_worker);
+ 
+ 	local_bh_disable();
+@@ -2149,6 +2152,10 @@ skip_coredump:
+ 
+ void mt7996_reset(struct mt7996_dev *dev)
+ {
++	dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n",
++			 wiphy_name(dev->mt76.hw->wiphy),
++			 READ_ONCE(dev->recovery.state));
++
+ 	if (!dev->recovery.hw_init_done)
+ 		return;
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 8e5b3c3..561c1cd 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -448,6 +448,7 @@ int mt7996_dma_init(struct mt7996_dev *dev);
+ void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+ void mt7996_dma_cleanup(struct mt7996_dev *dev);
++void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset);
+ void mt7996_init_txpower(struct mt7996_dev *dev,
+ 			 struct ieee80211_supported_band *sband);
+ int mt7996_txbf_init(struct mt7996_dev *dev);
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
new file mode 100644
index 0000000..3d4d1c0
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch
@@ -0,0 +1,598 @@
+From cf66e6fc90e7a12209bd0a3d9b687b37f7324718 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Fri, 19 May 2023 14:16:50 +0800
+Subject: [PATCH] wifi: mt76: mt7996: add firmware WA's coredump.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Change-Id: I51f115b4ae15bc0f871f93652570d72511dbf880
+---
+ mt7996/coredump.c | 180 ++++++++++++++++++++++++++++++----------------
+ mt7996/coredump.h |  35 ++++++---
+ mt7996/mac.c      |  31 +++++---
+ mt7996/mcu.c      |   5 ++
+ mt7996/mt7996.h   |   7 +-
+ mt7996/regs.h     |   7 +-
+ 6 files changed, 182 insertions(+), 83 deletions(-)
+
+diff --git a/mt7996/coredump.c b/mt7996/coredump.c
+index ccab0d7b..60b88085 100644
+--- a/mt7996/coredump.c
++++ b/mt7996/coredump.c
+@@ -7,11 +7,11 @@
+ #include <linux/utsname.h>
+ #include "coredump.h"
+ 
+-static bool coredump_memdump;
++static bool coredump_memdump = true;
+ module_param(coredump_memdump, bool, 0644);
+ MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory");
+ 
+-static const struct mt7996_mem_region mt7996_mem_regions[] = {
++static const struct mt7996_mem_region mt7996_wm_mem_regions[] = {
+ 	{
+ 		.start = 0x00800000,
+ 		.len = 0x0004ffff,
+@@ -44,27 +44,55 @@ static const struct mt7996_mem_region mt7996_mem_regions[] = {
+ 	},
+ };
+ 
++static const struct mt7996_mem_region mt7996_wa_mem_regions[] = {
++	{
++		.start = 0xE0000000,
++		.len = 0x0000ffff,
++		.name = "CRAM",
++	},
++	{
++		.start = 0xE0010000,
++		.len = 0x000117ff,
++		.name = "CRAM2",
++	},
++	{
++		.start = 0x10000000,
++		.len = 0x0001bfff,
++		.name = "ILM",
++	},
++	{
++		.start = 0x10200000,
++		.len = 0x00063fff,
++		.name = "DLM",
++	},
++};
++
+ const struct mt7996_mem_region*
+-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
++mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num)
+ {
+ 	switch (mt76_chip(&dev->mt76)) {
+ 	case 0x7990:
+ 	case 0x7991:
+-		*num = ARRAY_SIZE(mt7996_mem_regions);
+-		return &mt7996_mem_regions[0];
++		if (type == MT7996_RAM_TYPE_WA) {
++			*num = ARRAY_SIZE(mt7996_wa_mem_regions);
++			return &mt7996_wa_mem_regions[0];
++		}
++
++		*num = ARRAY_SIZE(mt7996_wm_mem_regions);
++		return &mt7996_wm_mem_regions[0];
+ 	default:
+ 		return NULL;
+ 	}
+ }
+ 
+-static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
++static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev, u8 type)
+ {
+ 	const struct mt7996_mem_region *mem_region;
+ 	size_t size = 0;
+ 	u32 num;
+ 	int i;
+ 
+-	mem_region = mt7996_coredump_get_mem_layout(dev, &num);
++	mem_region = mt7996_coredump_get_mem_layout(dev, type, &num);
+ 	if (!mem_region)
+ 		return 0;
+ 
+@@ -81,14 +109,13 @@ static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
+ 	return size;
+ }
+ 
+-struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
++struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
+ {
+-	struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
++	struct mt7996_crash_data *crash_data = dev->coredump.crash_data[type];
+ 
+ 	lockdep_assert_held(&dev->dump_mutex);
+ 
+-	if (coredump_memdump &&
+-	    !mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500))
++	if (!coredump_memdump)
+ 		return NULL;
+ 
+ 	guid_gen(&crash_data->guid);
+@@ -98,12 +125,15 @@ struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
+ }
+ 
+ static void
+-mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
++mt7996_coredump_fw_state(struct mt7996_dev *dev, u8 type, struct mt7996_coredump *dump,
+ 			 bool *exception)
+ {
+-	u32 count;
++	u32 count, reg = MT_FW_WM_DUMP_STATE;
++
++	if (type == MT7996_RAM_TYPE_WA)
++		reg = MT_FW_WA_DUMP_STATE;
+ 
+-	count = mt76_rr(dev, MT_FW_ASSERT_CNT);
++	count = mt76_rr(dev, reg);
+ 
+ 	/* normal mode: driver can manually trigger assert for detail info */
+ 	if (!count)
+@@ -115,53 +145,59 @@ mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
+ }
+ 
+ static void
+-mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump,
++mt7996_coredump_fw_stack(struct mt7996_dev *dev, u8 type, struct mt7996_coredump *dump,
+ 			 bool exception)
+ {
+-	u32 oldest, i, idx;
++	u32 reg, i, offset = 0, val = MT7996_RAM_TYPE_WM;
+ 
+-	strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current));
++	if (type == MT7996_RAM_TYPE_WA) {
++		offset = MT_MCU_WA_EXCP_BASE - MT_MCU_WM_EXCP_BASE;
++		val = MT7996_RAM_TYPE_WA;
++	}
+ 
+-	/* 0: WM PC log output */
+-	mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0);
++	/* 0: WM PC log output, 1: WA PC log output  */
++	mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, val);
+ 	/* choose 33th PC log buffer to read current PC index */
+ 	mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f);
+ 
+ 	/* read current PC */
+-	dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
++	for (i = 0; i < 10; i++)
++		dump->pc_cur[i] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
+ 
+ 	/* stop call stack record */
+ 	if (!exception) {
+-		mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
+-		mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
++		mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL + offset, BIT(0));
++		mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL + offset, BIT(0));
+ 	}
+ 
+-	oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL,
+-				     GENMASK(20, 16)) + 2;
+-	for (i = 0; i < 16; i++) {
+-		idx = ((oldest + 2 * i + 1) % 32);
+-		dump->pc_stack[i + 1] =
+-			mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4);
++	/* read PC log */
++	dump->pc_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_PC_CTRL + offset);
++	dump->pc_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS,
++				     dump->pc_dbg_ctrl);
++	for (i = 0; i < 32; i++) {
++		reg = MT_MCU_WM_EXCP_PC_LOG + i * 4 + offset;
++		dump->pc_stack[i] = mt76_rr(dev, reg);
+ 	}
+ 
+-	oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL,
+-				     GENMASK(20, 16)) + 2;
+-	for (i = 0; i < 16; i++) {
+-		idx = ((oldest + 2 * i + 1) % 32);
+-		dump->lr_stack[i] =
+-			mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4);
++	/* read LR log */
++	dump->lr_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_LR_CTRL + offset);
++	dump->lr_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS,
++				     dump->lr_dbg_ctrl);
++	for (i = 0; i < 32; i++) {
++		reg = MT_MCU_WM_EXCP_LR_LOG + i * 4 + offset;
++		dump->lr_stack[i] = mt76_rr(dev, reg);
+ 	}
+ 
+ 	/* start call stack record */
+ 	if (!exception) {
+-		mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
+-		mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
++		mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL + offset, BIT(0));
++		mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL + offset, BIT(0));
+ 	}
+ }
+ 
+-static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
++static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type)
+ {
+-	struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
++	struct mt7996_crash_data *crash_data = dev->coredump.crash_data[type];
+ 	struct mt7996_coredump *dump;
+ 	struct mt7996_coredump_mem *dump_mem;
+ 	size_t len, sofar = 0, hdr_len = sizeof(*dump);
+@@ -186,20 +222,31 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
+ 
+ 	dump = (struct mt7996_coredump *)(buf);
+ 	dump->len = len;
++	dump->hdr_len = hdr_len;
+ 
+ 	/* plain text */
+ 	strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic));
+ 	strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel));
++	strscpy(dump->fw_type, ((type == MT7996_RAM_TYPE_WA) ? "WA" : "WM"),
++		sizeof(dump->fw_type));
+ 	strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version,
+ 		sizeof(dump->fw_ver));
++	strscpy(dump->fw_patch_date, dev->patch_build_date,
++		sizeof(dump->fw_patch_date));
++	strscpy(dump->fw_ram_date[MT7996_RAM_TYPE_WM],
++		dev->ram_build_date[MT7996_RAM_TYPE_WM],
++		MT7996_BUILD_TIME_LEN);
++	strscpy(dump->fw_ram_date[MT7996_RAM_TYPE_WA],
++		dev->ram_build_date[MT7996_RAM_TYPE_WA],
++		MT7996_BUILD_TIME_LEN);
+ 
+ 	guid_copy(&dump->guid, &crash_data->guid);
+ 	dump->tv_sec = crash_data->timestamp.tv_sec;
+ 	dump->tv_nsec = crash_data->timestamp.tv_nsec;
+ 	dump->device_id = mt76_chip(&dev->mt76);
+ 
+-	mt7996_coredump_fw_state(dev, dump, &exception);
+-	mt7996_coredump_fw_stack(dev, dump, exception);
++	mt7996_coredump_fw_state(dev, type, dump, &exception);
++	mt7996_coredump_fw_stack(dev, type, dump, exception);
+ 
+ 	/* gather memory content */
+ 	dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
+@@ -213,17 +260,19 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
+ 	return dump;
+ }
+ 
+-int mt7996_coredump_submit(struct mt7996_dev *dev)
++int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
+ {
+ 	struct mt7996_coredump *dump;
+ 
+-	dump = mt7996_coredump_build(dev);
++	dump = mt7996_coredump_build(dev, type);
+ 	if (!dump) {
+ 		dev_warn(dev->mt76.dev, "no crash dump data found\n");
+ 		return -ENODATA;
+ 	}
+ 
+ 	dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL);
++	dev_info(dev->mt76.dev, "%s coredump completed\n",
++		 wiphy_name(dev->mt76.hw->wiphy));
+ 
+ 	return 0;
+ }
+@@ -231,23 +280,26 @@ int mt7996_coredump_submit(struct mt7996_dev *dev)
+ int mt7996_coredump_register(struct mt7996_dev *dev)
+ {
+ 	struct mt7996_crash_data *crash_data;
++	int i;
+ 
+-	crash_data = vzalloc(sizeof(*dev->coredump.crash_data));
+-	if (!crash_data)
+-		return -ENOMEM;
++	for (i = 0; i < MT7996_COREDUMP_MAX; i++) {
++		crash_data = vzalloc(sizeof(*dev->coredump.crash_data[i]));
++		if (!crash_data)
++			return -ENOMEM;
+ 
+-	dev->coredump.crash_data = crash_data;
++		dev->coredump.crash_data[i] = crash_data;
+ 
+-	if (coredump_memdump) {
+-		crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev);
+-		if (!crash_data->memdump_buf_len)
+-			/* no memory content */
+-			return 0;
++		if (coredump_memdump) {
++			crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev, i);
++			if (!crash_data->memdump_buf_len)
++				/* no memory content */
++				return 0;
+ 
+-		crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
+-		if (!crash_data->memdump_buf) {
+-			vfree(crash_data);
+-			return -ENOMEM;
++			crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
++			if (!crash_data->memdump_buf) {
++				vfree(crash_data);
++				return -ENOMEM;
++			}
+ 		}
+ 	}
+ 
+@@ -256,13 +308,17 @@ int mt7996_coredump_register(struct mt7996_dev *dev)
+ 
+ void mt7996_coredump_unregister(struct mt7996_dev *dev)
+ {
+-	if (dev->coredump.crash_data->memdump_buf) {
+-		vfree(dev->coredump.crash_data->memdump_buf);
+-		dev->coredump.crash_data->memdump_buf = NULL;
+-		dev->coredump.crash_data->memdump_buf_len = 0;
+-	}
++	int i;
+ 
+-	vfree(dev->coredump.crash_data);
+-	dev->coredump.crash_data = NULL;
++	for (i = 0; i < MT7996_COREDUMP_MAX; i++) {
++		if (dev->coredump.crash_data[i]->memdump_buf) {
++			vfree(dev->coredump.crash_data[i]->memdump_buf);
++			dev->coredump.crash_data[i]->memdump_buf = NULL;
++			dev->coredump.crash_data[i]->memdump_buf_len = 0;
++		}
++
++		vfree(dev->coredump.crash_data[i]);
++		dev->coredump.crash_data[i] = NULL;
++	}
+ }
+ 
+diff --git a/mt7996/coredump.h b/mt7996/coredump.h
+index af2ba219..01ed3731 100644
+--- a/mt7996/coredump.h
++++ b/mt7996/coredump.h
+@@ -6,10 +6,13 @@
+ 
+ #include "mt7996.h"
+ 
++#define MT7996_COREDUMP_MAX	(MT7996_RAM_TYPE_WA + 1)
++
+ struct mt7996_coredump {
+ 	char magic[16];
+ 
+ 	u32 len;
++	u32 hdr_len;
+ 
+ 	guid_t guid;
+ 
+@@ -21,17 +24,28 @@ struct mt7996_coredump {
+ 	char kernel[64];
+ 	/* firmware version */
+ 	char fw_ver[ETHTOOL_FWVERS_LEN];
++	char fw_patch_date[MT7996_BUILD_TIME_LEN];
++	char fw_ram_date[MT7996_COREDUMP_MAX][MT7996_BUILD_TIME_LEN];
+ 
+ 	u32 device_id;
+ 
++	/* fw type */
++	char fw_type[8];
++
+ 	/* exception state */
+ 	char fw_state[12];
+ 
+ 	/* program counters */
+-	char pc_current[16];
+-	u32 pc_stack[17];
+-	/* link registers */
+-	u32 lr_stack[16];
++	u32 pc_dbg_ctrl;
++	u32 pc_cur_idx;
++	u32 pc_cur[10];
++	/* PC registers */
++	u32 pc_stack[32];
++
++	u32 lr_dbg_ctrl;
++	u32 lr_cur_idx;
++	/* LR registers */
++	u32 lr_stack[32];
+ 
+ 	/* memory content */
+ 	u8 data[];
+@@ -43,6 +57,7 @@ struct mt7996_coredump_mem {
+ } __packed;
+ 
+ struct mt7996_mem_hdr {
++	char name[64];
+ 	u32 start;
+ 	u32 len;
+ 	u8 data[];
+@@ -58,27 +73,27 @@ struct mt7996_mem_region {
+ #ifdef CONFIG_DEV_COREDUMP
+ 
+ const struct mt7996_mem_region *
+-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num);
+-struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev);
+-int mt7996_coredump_submit(struct mt7996_dev *dev);
++mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num);
++struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type);
++int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type);
+ int mt7996_coredump_register(struct mt7996_dev *dev);
+ void mt7996_coredump_unregister(struct mt7996_dev *dev);
+ 
+ #else /* CONFIG_DEV_COREDUMP */
+ 
+ static inline const struct mt7996_mem_region *
+-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
++mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num)
+ {
+ 	return NULL;
+ }
+ 
+-static inline int mt7996_coredump_submit(struct mt7996_dev *dev)
++static inline int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
+ {
+ 	return 0;
+ }
+ 
+ static inline struct
+-mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
++mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
+ {
+ 	return NULL;
+ }
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 986031f5..724af82a 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2082,28 +2082,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ }
+ 
+ /* firmware coredump */
+-void mt7996_mac_dump_work(struct work_struct *work)
++void mt7996_mac_fw_coredump(struct mt7996_dev *dev, u8 type)
+ {
+ 	const struct mt7996_mem_region *mem_region;
+ 	struct mt7996_crash_data *crash_data;
+-	struct mt7996_dev *dev;
+ 	struct mt7996_mem_hdr *hdr;
+ 	size_t buf_len;
+ 	int i;
+ 	u32 num;
+ 	u8 *buf;
+ 
+-	dev = container_of(work, struct mt7996_dev, dump_work);
+-
+ 	mutex_lock(&dev->dump_mutex);
+ 
+-	crash_data = mt7996_coredump_new(dev);
++	crash_data = mt7996_coredump_new(dev, type);
+ 	if (!crash_data) {
+ 		mutex_unlock(&dev->dump_mutex);
+-		goto skip_coredump;
++		return;
+ 	}
+ 
+-	mem_region = mt7996_coredump_get_mem_layout(dev, &num);
++	mem_region = mt7996_coredump_get_mem_layout(dev, type, &num);
+ 	if (!mem_region || !crash_data->memdump_buf_len) {
+ 		mutex_unlock(&dev->dump_mutex);
+ 		goto skip_memdump;
+@@ -2113,6 +2110,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
+ 	buf_len = crash_data->memdump_buf_len;
+ 
+ 	/* dumping memory content... */
++	dev_info(dev->mt76.dev, "%s start coredump for %s\n",
++		 wiphy_name(dev->mt76.hw->wiphy),
++		 ((type == MT7996_RAM_TYPE_WA) ? "WA" : "WM"));
+ 	memset(buf, 0, buf_len);
+ 	for (i = 0; i < num; i++) {
+ 		if (mem_region->len > buf_len) {
+@@ -2129,6 +2129,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
+ 		mt7996_memcpy_fromio(dev, buf, mem_region->start,
+ 				     mem_region->len);
+ 
++		strscpy(hdr->name, mem_region->name, sizeof(mem_region->name));
+ 		hdr->start = mem_region->start;
+ 		hdr->len = mem_region->len;
+ 
+@@ -2145,8 +2146,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
+ 	mutex_unlock(&dev->dump_mutex);
+ 
+ skip_memdump:
+-	mt7996_coredump_submit(dev);
+-skip_coredump:
++	mt7996_coredump_submit(dev, type);
++}
++
++void mt7996_mac_dump_work(struct work_struct *work)
++{
++	struct mt7996_dev *dev;
++
++	dev = container_of(work, struct mt7996_dev, dump_work);
++	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
++		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WA);
++
++	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT)
++		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WM);
++
+ 	queue_work(dev->mt76.wq, &dev->reset_work);
+ }
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 38292da3..14f7a43f 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2458,6 +2458,8 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
+ 
+ 	dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
+ 		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
++	memcpy(dev->patch_build_date, hdr->build_date,
++	       sizeof(dev->patch_build_date));
+ 
+ 	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
+ 		struct mt7996_patch_sec *sec;
+@@ -2584,6 +2586,9 @@ static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
+ 	}
+ 
+ 	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
++	memcpy(dev->ram_build_date[ram_type],
++	       hdr->build_date,
++	       sizeof(dev->ram_build_date[ram_type]));
+ 	dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n",
+ 		 fw_type, hdr->fw_ver, hdr->build_date);
+ 
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 561c1cdc..f59dce77 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -58,6 +58,8 @@
+ #define MT7996_CRIT_TEMP		110
+ #define MT7996_MAX_TEMP			120
+ 
++#define MT7996_BUILD_TIME_LEN		24
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -68,6 +70,7 @@ enum mt7996_ram_type {
+ 	MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
+ 	MT7996_RAM_TYPE_WA,
+ 	MT7996_RAM_TYPE_DSP,
++	__MT7996_RAM_TYPE_MAX,
+ };
+ 
+ enum mt7996_txq_id {
+@@ -306,9 +309,11 @@ struct mt7996_dev {
+ 	struct mutex dump_mutex;
+ #ifdef CONFIG_DEV_COREDUMP
+ 	struct {
+-		struct mt7996_crash_data *crash_data;
++		struct mt7996_crash_data *crash_data[__MT7996_RAM_TYPE_MAX];
+ 	} coredump;
+ #endif
++	char patch_build_date[MT7996_BUILD_TIME_LEN];
++	char ram_build_date[__MT7996_RAM_TYPE_MAX][MT7996_BUILD_TIME_LEN];
+ 
+ 	struct list_head sta_rc_list;
+ 	struct list_head sta_poll_list;
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 86da1bf8..c054586d 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -482,7 +482,8 @@ enum base_rev {
+ 
+ /* FW MODE SYNC */
+ #define MT_FW_ASSERT_CNT			0x02208274
+-#define MT_FW_DUMP_STATE			0x02209e90
++#define MT_FW_WM_DUMP_STATE			0x02209e90
++#define MT_FW_WA_DUMP_STATE			0x7C05B080
+ 
+ #define MT_SWDEF_BASE				0x00401400
+ 
+@@ -580,11 +581,15 @@ enum base_rev {
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR		BIT(29)
+ 
+ /* CONN MCU EXCP CON */
++#define MT_MCU_WA_EXCP_BASE			0x890d0000
+ #define MT_MCU_WM_EXCP_BASE			0x89050000
++
+ #define MT_MCU_WM_EXCP(ofs)			(MT_MCU_WM_EXCP_BASE + (ofs))
+ #define MT_MCU_WM_EXCP_PC_CTRL			MT_MCU_WM_EXCP(0x100)
++#define MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS	GENMASK(20, 16)
+ #define MT_MCU_WM_EXCP_PC_LOG			MT_MCU_WM_EXCP(0x104)
+ #define MT_MCU_WM_EXCP_LR_CTRL			MT_MCU_WM_EXCP(0x200)
++#define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS	GENMASK(20, 16)
+ #define MT_MCU_WM_EXCP_LR_LOG			MT_MCU_WM_EXCP(0x204)
+ 
+ #endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
new file mode 100644
index 0000000..6864e26
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch
@@ -0,0 +1,184 @@
+From 18ed969cf7bfdaa059ed946f5bacd62a2ebf9ffe Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 23 May 2023 15:49:03 +0800
+Subject: [PATCH 35/39] wifi: mt76: mt7996: make band capability init flexible
+
+There're some variations of mt7996 chipset which only support two-band,
+so parse the adie combination to correctly set band capability.
+
+Change-Id: Ifcb49504f02f5cc6a23c626e30b4f0e1360fe157
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mt7996/dma.c    |  8 ++++----
+ mt7996/init.c   | 29 ++++++++++++++++++-----------
+ mt7996/mcu.c    | 13 +++++--------
+ mt7996/mt7996.h | 11 +++++++++++
+ mt7996/regs.h   |  3 +++
+ 5 files changed, 41 insertions(+), 23 deletions(-)
+
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 6a21e3e..f01cea5 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -159,13 +159,13 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 
+ 	irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
+ 
+-	if (!dev->mphy.band_idx)
++	if (mt7996_band_valid(dev, MT_BAND0))
+ 		irq_mask |= MT_INT_BAND0_RX_DONE;
+ 
+-	if (dev->dbdc_support)
++	if (mt7996_band_valid(dev, MT_BAND1))
+ 		irq_mask |= MT_INT_BAND1_RX_DONE;
+ 
+-	if (dev->tbtc_support)
++	if (mt7996_band_valid(dev, MT_BAND2))
+ 		irq_mask |= MT_INT_BAND2_RX_DONE;
+ 
+ done:
+@@ -334,7 +334,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
++	if (mt7996_band_valid(dev, MT_BAND2)) {
+ 		/* rx data queue for band2 */
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ 				       MT_RXQ_ID(MT_RXQ_BAND2),
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 0562439..0825e0b 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -529,11 +529,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	u32 mac_ofs, hif1_ofs = 0;
+ 	int ret;
+ 
+-	if (band != MT_BAND1 && band != MT_BAND2)
+-		return 0;
+-
+-	if ((band == MT_BAND1 && !dev->dbdc_support) ||
+-	    (band == MT_BAND2 && !dev->tbtc_support))
++	if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
+ 		return 0;
+ 
+ 	if (phy)
+@@ -648,8 +644,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ 
+ 	INIT_WORK(&dev->init_work, mt7996_init_work);
+ 
+-	dev->dbdc_support = true;
+-	dev->tbtc_support = true;
++	dev->dbdc_support = mt7996_band_valid(dev, MT_BAND1) ||
++			    mt7996_band_valid(dev, MT_BAND2);
++	dev->tbtc_support = mt7996_band_valid(dev, MT_BAND1) &&
++			    mt7996_band_valid(dev, MT_BAND2);
+ 
+ 	ret = mt7996_dma_init(dev);
+ 	if (ret)
+@@ -1089,8 +1087,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+-
+ 	ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
+ 	if (ret)
+ 		return ret;
+@@ -1099,13 +1095,24 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
++
+ 	dev->recovery.hw_init_done = true;
+ 
+ 	ret = mt7996_init_debugfs(&dev->phy);
+ 	if (ret)
+-		return ret;
++		goto error;
+ 
+-	return mt7996_coredump_register(dev);
++	ret = mt7996_coredump_register(dev);
++	if (ret)
++		goto error;
++
++	return 0;
++
++error:
++	cancel_work_sync(&dev->init_work);
++
++	return ret;
+ }
+ 
+ void mt7996_unregister_device(struct mt7996_dev *dev)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index c647979..9fb800a 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2767,7 +2767,7 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
+ {
+ 	struct uni_header hdr = {};
+ 	struct sk_buff *skb;
+-	int len, num;
++	int len, num, i;
+ 
+ 	num = 2 + 2 * (dev->dbdc_support + dev->tbtc_support);
+ 	len = sizeof(hdr) + num * sizeof(struct vow_rx_airtime);
+@@ -2777,13 +2777,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
+ 
+ 	skb_put_data(skb, &hdr, sizeof(hdr));
+ 
+-	mt7996_add_rx_airtime_tlv(skb, dev->mt76.phy.band_idx);
+-
+-	if (dev->dbdc_support)
+-		mt7996_add_rx_airtime_tlv(skb, MT_BAND1);
+-
+-	if (dev->tbtc_support)
+-		mt7996_add_rx_airtime_tlv(skb, MT_BAND2);
++	for (i = 0; i < __MT_MAX_BAND; i++) {
++		if (mt7996_band_valid(dev, i))
++			mt7996_add_rx_airtime_tlv(skb, i);
++	}
+ 
+ 	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ 				     MCU_WM_UNI_CMD(VOW), true);
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index f59dce7..488f59c 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -431,6 +431,17 @@ mt7996_phy3(struct mt7996_dev *dev)
+ 	return __mt7996_phy(dev, MT_BAND2);
+ }
+ 
++static inline bool
++mt7996_band_valid(struct mt7996_dev *dev, u8 band)
++{
++	/* tri-band support */
++	if (band <= MT_BAND2 &&
++	    mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
++		return true;
++
++	return band == MT_BAND0 || band == MT_BAND2;
++}
++
+ extern const struct ieee80211_ops mt7996_ops;
+ extern struct pci_driver mt7996_pci_driver;
+ extern struct pci_driver mt7996_hif_driver;
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index c054586..3a5914c 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -546,6 +546,9 @@ enum base_rev {
+ #define MT_TOP_MISC				MT_TOP(0xf0)
+ #define MT_TOP_MISC_FW_STATE			GENMASK(2, 0)
+ 
++#define MT_PAD_GPIO				0x700056f0
++#define MT_PAD_GPIO_ADIE_COMB			GENMASK(16, 15)
++
+ #define MT_HW_REV				0x70010204
+ #define MT_WF_SUBSYS_RST			0x70028600
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
new file mode 100644
index 0000000..c0ce85d
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch
@@ -0,0 +1,272 @@
+From 18f990de206c3301d3ae72cfeef40dfb3b361fb0 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 8 May 2023 09:03:50 +0800
+Subject: [PATCH 36/39] wifi: mt76: mt7996: enable SCS feature for mt7996
+ driver
+
+Enable Smart Carrier Sense algorithn by default to improve performance
+in a noisy environment.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt76_connac_mcu.h |   1 +
+ mt7996/init.c     |   1 +
+ mt7996/main.c     |   7 +++
+ mt7996/mcu.c      | 123 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      |   6 +++
+ mt7996/mt7996.h   |  16 ++++++
+ 6 files changed, 154 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 97f874b..bfec420 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1213,6 +1213,7 @@ enum {
+ 	MCU_UNI_CMD_GET_MIB_INFO = 0x22,
+ 	MCU_UNI_CMD_SNIFFER = 0x24,
+ 	MCU_UNI_CMD_SR = 0x25,
++	MCU_UNI_CMD_SCS = 0x26,
+ 	MCU_UNI_CMD_ROC = 0x27,
+ 	MCU_UNI_CMD_TXPOWER = 0x2b,
+ 	MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 0825e0b..1072874 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -1058,6 +1058,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	dev->mt76.phy.priv = &dev->phy;
+ 	INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
+ 	INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
++	INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll);
+ 	INIT_LIST_HEAD(&dev->sta_rc_list);
+ 	INIT_LIST_HEAD(&dev->sta_poll_list);
+ 	INIT_LIST_HEAD(&dev->twt_list);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 520f250..20b89a7 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -73,11 +73,17 @@ int mt7996_run(struct ieee80211_hw *hw)
+ 	if (ret)
+ 		goto out;
+ 
++	ret = mt7996_mcu_set_scs(phy, SCS_ENABLE);
++	if (ret)
++		goto out;
++
+ 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+ 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+ 				     MT7996_WATCHDOG_TIME);
+ 
++	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
++
+ 	if (!running)
+ 		mt7996_mac_reset_counters(phy);
+ 
+@@ -105,6 +111,7 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 
+ 	cancel_delayed_work_sync(&phy->mt76->mac_work);
++	cancel_delayed_work_sync(&dev->scs_work);
+ 
+ 	mutex_lock(&dev->mt76.mutex);
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 9fb800a..a5c473a 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4190,3 +4190,126 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ 	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TXPOWER),
+ 				 &req, sizeof(req), false);
+ }
++
++int mt7996_mcu_set_scs_stats(struct mt7996_phy *phy)
++{
++	struct mt7996_scs_ctrl ctrl = phy->scs_ctrl;
++	struct {
++		u8 band_idx;
++		u8 _rsv[3];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 _rsv2[6];
++		s8 min_rssi;
++		u8 _rsv3;
++	} __packed req = {
++		.band_idx = phy->mt76->band_idx,
++		.tag = cpu_to_le16(UNI_CMD_SCS_SEND_DATA),
++		.len = cpu_to_le16(sizeof(req) - 4),
++
++		.min_rssi = ctrl.sta_min_rssi,
++	};
++
++	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
++				 &req, sizeof(req), false);
++}
++
++void mt7996_sta_rssi_work(void *data, struct ieee80211_sta *sta)
++{
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++	struct mt7996_dev *dev = (struct mt7996_dev *)data;
++	struct mt7996_phy *poll_phy;
++	u8 band_idx = msta->wcid.phy_idx;
++
++	switch (band_idx) {
++	case MT_BAND0:
++		poll_phy = dev->mphy.priv;
++		break;
++	case MT_BAND1:
++		poll_phy = mt7996_phy2(dev);
++		break;
++	case MT_BAND2:
++		poll_phy = mt7996_phy3(dev);
++		break;
++	default:
++		poll_phy = NULL;
++		break;
++	}
++
++	if (!poll_phy->scs_ctrl.scs_enable)
++		return;
++
++	if (poll_phy->scs_ctrl.sta_min_rssi > msta->ack_signal)
++		poll_phy->scs_ctrl.sta_min_rssi = msta->ack_signal;
++}
++
++void mt7996_mcu_scs_sta_poll(struct work_struct *work)
++{
++	struct mt7996_dev *dev = container_of(work, struct mt7996_dev,
++				 scs_work.work);
++	bool scs_enable_flag = false;
++	u8 i;
++
++	ieee80211_iterate_stations_atomic(dev->mphy.hw, mt7996_sta_rssi_work, dev);
++
++	for (i = 0; i < __MT_MAX_BAND; i++) {
++		struct mt7996_phy *phy;
++
++		switch (i) {
++		case MT_BAND0:
++			phy = dev->mphy.priv;
++			break;
++		case MT_BAND1:
++			phy = mt7996_phy2(dev);
++			break;
++		case MT_BAND2:
++			phy = mt7996_phy3(dev);
++			break;
++		default:
++			phy = NULL;
++			break;
++		}
++
++		if (phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state) &&
++		    phy->scs_ctrl.scs_enable) {
++			scs_enable_flag = true;
++			if (mt7996_mcu_set_scs_stats(phy))
++				dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n");
++			phy->scs_ctrl.sta_min_rssi = 0;
++		}
++	}
++
++	if (scs_enable_flag)
++		ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
++}
++
++
++int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct {
++		u8 band_idx;
++		u8 _rsv[3];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 scs_enable;
++		u8 _rsv2[3];
++	} __packed req = {
++		.band_idx = phy->mt76->band_idx,
++		.tag = cpu_to_le16(UNI_CMD_SCS_ENABLE),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.scs_enable = enable,
++	};
++
++	phy->scs_ctrl.scs_enable = enable;
++
++	if (enable == SCS_ENABLE)
++		ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
++
++	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
++				 &req, sizeof(req), false);
++}
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index eed7371..eb63441 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -757,6 +757,12 @@ enum {
+ 	MT7996_SEC_MODE_MAX,
+ };
+ 
++enum {
++	UNI_CMD_SCS_SEND_DATA,
++	UNI_CMD_SCS_SET_PD_THR_RANGE = 2,
++	UNI_CMD_SCS_ENABLE,
++};
++
+ #define MT7996_PATCH_SEC		GENMASK(31, 24)
+ #define MT7996_PATCH_SCRAMBLE_KEY	GENMASK(15, 8)
+ #define MT7996_PATCH_AES_KEY		GENMASK(7, 0)
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 488f59c..f78f1fd 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -222,6 +222,17 @@ struct mt7996_hif {
+ 	int irq;
+ };
+ 
++
++struct mt7996_scs_ctrl {
++	u8 scs_enable;
++	s8 sta_min_rssi;
++};
++
++enum {
++	SCS_DISABLE = 0,
++	SCS_ENABLE,
++};
++
+ struct mt7996_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -253,6 +264,8 @@ struct mt7996_phy {
+ 
+ 	bool has_aux_rx;
+ 
++	struct mt7996_scs_ctrl scs_ctrl;
++
+ #ifdef CONFIG_NL80211_TESTMODE
+ 	struct {
+ 		u32 *reg_backup;
+@@ -295,6 +308,7 @@ struct mt7996_dev {
+ 	struct work_struct rc_work;
+ 	struct work_struct dump_work;
+ 	struct work_struct reset_work;
++	struct delayed_work scs_work;
+ 	wait_queue_head_t reset_wait;
+ 	struct {
+ 		u32 state;
+@@ -535,6 +549,8 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
++int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
++void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+ 
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
new file mode 100644
index 0000000..5dc8109
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch
@@ -0,0 +1,237 @@
+From de92f88f5c00cf1069df00bb89f50281b0b2d05e Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 12 May 2023 16:24:53 +0800
+Subject: [PATCH 37/39] wifi: mt76: mt7996: add beacon duplicate tx mode
+ support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac_mcu.h |  1 +
+ mt7996/init.c     |  6 ++++--
+ mt7996/mac.c      | 11 -----------
+ mt7996/main.c     | 18 +++++++++---------
+ mt7996/mcu.c      | 30 ++++++++++++++++++++++++++++++
+ mt7996/mcu.h      | 20 ++++++++++++++++++++
+ mt7996/mt7996.h   |  8 +++++---
+ 7 files changed, 69 insertions(+), 25 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index bfec420..4bb9508 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1224,6 +1224,7 @@ enum {
+ 	MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
+ 	MCU_UNI_CMD_THERMAL = 0x35,
+ 	MCU_UNI_CMD_VOW = 0x37,
++	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
+ 	MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
+ 	MCU_UNI_CMD_RRO = 0x57,
+ 	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 1072874..9eba689 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -351,6 +351,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
+ 
+ 	phy->slottime = 9;
++	phy->beacon_rate = -1;
+ 
+ 	hw->sta_data_size = sizeof(struct mt7996_sta);
+ 	hw->vif_data_size = sizeof(struct mt7996_vif);
+@@ -459,11 +460,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+ 
+ 	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
+ 		u16 rate = mt76_rates[i].hw_value;
+-		u16 idx = MT7996_BASIC_RATES_TBL + i;
++		/* odd index for driver, even index for firmware */
++		u16 idx = MT7996_BASIC_RATES_TBL + 2 * i;
+ 
+ 		rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
+ 		       FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
+-		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
++		mt7996_mcu_set_fixed_rate_table(&dev->phy, idx, rate, false);
+ 	}
+ }
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 724af82..05269e7 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -252,17 +252,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+ 		mt76_clear(dev, addr, BIT(5));
+ }
+ 
+-void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+-				     u8 tbl_idx, u16 rate_idx)
+-{
+-	u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
+-
+-	mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
+-	/* use wtbl spe idx */
+-	mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
+-	mt76_wr(dev, MT_WTBL_ITCR, ctrl);
+-}
+-
+ static void
+ mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
+ 				 struct ieee80211_radiotap_he *he,
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 20b89a7..2ed66e6 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -544,24 +544,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ 	struct mt76_phy *mphy = hw->priv;
+ 	u16 rate;
+-	u8 i, idx, ht;
++	u8 i, idx;
+ 
+ 	rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
+-	ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
+ 
+-	if (beacon && ht) {
+-		struct mt7996_dev *dev = mt7996_hw_dev(hw);
++	if (beacon) {
++		struct mt7996_phy *phy = mt7996_hw_phy(hw);
++
++		/* odd index for driver, even index for firmware */
++		idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
++		if (phy->beacon_rate != rate)
++			mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);
+ 
+-		/* must odd index */
+-		idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
+-		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
+ 		return idx;
+ 	}
+ 
+ 	idx = FIELD_GET(MT_TX_RATE_IDX, rate);
+ 	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
+ 		if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
+-			return MT7996_BASIC_RATES_TBL + i;
++			return MT7996_BASIC_RATES_TBL + 2 * i;
+ 
+ 	return mvif->basic_rates_idx;
+ }
+@@ -965,7 +966,6 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+ 	mt7996_set_stream_vht_txbf_caps(phy);
+ 	mt7996_set_stream_he_eht_caps(phy);
+ 
+-	/* TODO: update bmc_wtbl spe_idx when antenna changes */
+ 	mutex_unlock(&dev->mt76.mutex);
+ 
+ 	return 0;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a5c473a..b34c6b7 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4056,6 +4056,36 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+ }
+ 
++int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
++				    u16 rate_idx, bool beacon)
++{
++#define UNI_FIXED_RATE_TABLE_SET	0
++#define SPE_IXD_SELECT_TXD		0
++#define SPE_IXD_SELECT_BMC_WTBL		1
++	struct mt7996_dev *dev = phy->dev;
++	struct fixed_rate_table_ctrl req = {
++		.tag = cpu_to_le16(UNI_FIXED_RATE_TABLE_SET),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.table_idx = table_idx,
++		.rate_idx = cpu_to_le16(rate_idx),
++		.gi = 1,
++		.he_ltf = 1,
++	};
++	u8 band_idx = phy->mt76->band_idx;
++
++	if (beacon) {
++		req.spe_idx_sel = SPE_IXD_SELECT_TXD;
++		req.spe_idx = 24 + band_idx;
++		phy->beacon_rate = rate_idx;
++	} else {
++		req.spe_idx_sel = SPE_IXD_SELECT_BMC_WTBL;
++		req.spe_idx = 0;
++	}
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(FIXED_RATE_TABLE),
++				 &req, sizeof(req), false);
++}
++
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
+ {
+ 	struct {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index eb63441..e32767e 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -771,4 +771,24 @@ enum {
+ #define MT7996_SEC_KEY_IDX		GENMASK(2, 1)
+ #define MT7996_SEC_IV			BIT(3)
+ 
++struct fixed_rate_table_ctrl {
++	u8 _rsv[4];
++
++	__le16 tag;
++	__le16 len;
++
++	u8 table_idx;
++	u8 antenna_idx;
++	__le16 rate_idx;
++	u8 spe_idx_sel;
++	u8 spe_idx;
++	u8 gi;
++	u8 he_ltf;
++	bool ldpc;
++	bool txbf;
++	bool dynamic_bw;
++
++	u8 rsv[1];
++} __packed;
++
+ #endif
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index f78f1fd..286fc1e 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -48,7 +48,7 @@
+ #define MT7996_MAX_QUEUE		(__MT_RXQ_MAX +	__MT_MCUQ_MAX + 3)
+ 
+ /* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+-#define MT7996_BASIC_RATES_TBL		11
++#define MT7996_BASIC_RATES_TBL		31
+ #define MT7996_BEACON_RATES_TBL		25
+ 
+ #define MT7996_THERMAL_THROTTLE_MAX	100
+@@ -256,6 +256,8 @@ struct mt7996_phy {
+ 
+ 	u8 rdd_state;
+ 
++	u16 beacon_rate;
++
+ 	u32 rx_ampdu_ts;
+ 	u32 ampdu_ref;
+ 
+@@ -539,6 +541,8 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 		       u8 rx_sel, u8 val);
+ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
+ 				     struct cfg80211_chan_def *chandef);
++int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
++				    u16 rate_idx, bool beacon);
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
+@@ -606,8 +610,6 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
+ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
+ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+ 			      struct ieee80211_vif *vif, bool enable);
+-void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+-				     u8 tbl_idx, u16 rate_idx);
+ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ 			   struct sk_buff *skb, struct mt76_wcid *wcid,
+ 			   struct ieee80211_key_conf *key, int pid,
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch
new file mode 100644
index 0000000..10bbe3a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch
@@ -0,0 +1,40 @@
+From 39893cc863213984a9ab0ae279dbfe433a6fe90e Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Tue, 23 May 2023 21:18:59 +0800
+Subject: [PATCH 38/39] wifi: mt76: mt7996: fix DFS CAC tx emission issue after
+ 2nd interface up
+
+FW's channel state is set during the first wifi interface setup. If the switch reason for
+setting the tx/rx path during second-time wifi interface setup is CH_SWITCH_NORMAL,
+then the FW would perform runtime dpd channel calibration during DFS CAC, which leads to
+tx emission. Therefore, in order to bypass tx calibration during DFS CAC, set the switch reason
+to CH_SWITCH_DFS whenever chandef is set to DFS channel.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/mcu.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index b34c6b7..be5c908 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3211,12 +3211,12 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
+ 		.channel_band = ch_band[chandef->chan->band],
+ 	};
+ 
+-	if (tag == UNI_CHANNEL_RX_PATH ||
+-	    dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
++	if (dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
+ 		req.switch_reason = CH_SWITCH_NORMAL;
+ 	else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
+ 		req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
+-	else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
++	else if (cfg80211_chandef_valid(chandef) &&
++		 !cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
+ 					  NL80211_IFTYPE_AP))
+ 		req.switch_reason = CH_SWITCH_DFS;
+ 	else
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
new file mode 100644
index 0000000..c2fed58
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch
@@ -0,0 +1,27 @@
+From affb48f4b09fca1e4df1e2291c78ee01b877e40f Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Tue, 30 May 2023 11:27:01 +0800
+Subject: [PATCH 39/39] wifi: mt76: mt7996: fix bss rate tlv to sync firmware
+ change
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt7996/mcu.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index e32767e..549007f 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -259,7 +259,7 @@ struct bss_rate_tlv {
+ 	u8 short_preamble;
+ 	u8 bc_fixed_rate;
+ 	u8 mc_fixed_rate;
+-	u8 __rsv2[1];
++	u8 __rsv2[9];
+ } __packed;
+ 
+ struct bss_ra_tlv {
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch
new file mode 100644
index 0000000..b5a49a5
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch
@@ -0,0 +1,43 @@
+From da1c93b8c6480cfcd605cd8c19111a6df8c9f8b4 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Fri, 2 Jun 2023 15:12:34 +0800
+Subject: [PATCH] wifi: mt76: mt7996: fix beamformee ss subfield in EHT PHY
+ caps IE
+
+According to P802.11be_D2.1 Table 9-401I, the minimum value of Beamformee SS shall
+be 3. Fix it to ensure that the value of Beamformee SS subfield is at least 3.
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/init.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 9eba689a..96c4bb01 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -936,16 +936,17 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
+ 		IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
+ 		IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
+ 
++	val = max_t(u8, sts - 1, 3);
+ 	eht_cap_elem->phy_cap_info[0] |=
+-		u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
++		u8_encode_bits(u8_get_bits(val, BIT(0)),
+ 			       IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
+ 
+ 	eht_cap_elem->phy_cap_info[1] =
+-		u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),
++		u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)),
+ 			       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |
+-		u8_encode_bits(sts - 1,
++		u8_encode_bits(val,
+ 			       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) |
+-		u8_encode_bits(sts - 1,
++		u8_encode_bits(val,
+ 			       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
+ 
+ 	eht_cap_elem->phy_cap_info[2] =
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
similarity index 90%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
index 89d1cdd..cb5d3bb 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0999-wifi-mt76-mt7996-for-build-pass.patch
@@ -1,7 +1,7 @@
-From c187058bfc83a80b3cfbfed4ce0c73ece6efb1fe Mon Sep 17 00:00:00 2001
+From 83bb8ec37f85161b08f4eb2abf6a9a0530cfc189 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 3 Nov 2022 00:27:17 +0800
-Subject: [PATCH 0999/1001] mt76: mt7996: for build pass
+Subject: [PATCH 0999/1015] wifi: mt76: mt7996: for build pass
 
 Change-Id: Ieb44c33ee6e6a2e6058c1ef528404c1a1cbcfdaf
 ---
@@ -34,10 +34,10 @@
  	return 0;
  }
 diff --git a/dma.c b/dma.c
-index f560d37d..ffc5b553 100644
+index f2b1b2ac..e1e9062b 100644
 --- a/dma.c
 +++ b/dma.c
-@@ -858,7 +858,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -859,7 +859,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		    !(dev->drv->rx_check(dev, data, len)))
  			goto free_frag;
  
@@ -116,10 +116,10 @@
  #define fw_name(_dev, name, ...)	({			\
  	char *_fw;						\
 diff --git a/mt7996/dma.c b/mt7996/dma.c
-index 53414346..733d1228 100644
+index f01cea5e..b8f253d0 100644
 --- a/mt7996/dma.c
 +++ b/mt7996/dma.c
-@@ -343,8 +343,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+@@ -360,8 +360,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
  	if (ret < 0)
  		return ret;
  
@@ -129,9 +129,9 @@
 +			  mt7996_poll_tx, NAPI_POLL_WEIGHT);
  	napi_enable(&dev->mt76.tx_napi);
  
- 	mt7996_dma_enable(dev);
+ 	mt7996_dma_enable(dev, false);
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index f5e95460..50f2227f 100644
+index 9840c77d..b81ed64c 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
 @@ -121,6 +121,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
@@ -143,7 +143,7 @@
  		dev->has_eht = !(cap & MODE_HE_ONLY);
  		dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 24adeb12..f2bfbd8a 100644
+index 871d32a4..58893348 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
 @@ -5,6 +5,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1000-mt76-mt7996-add-debug-tool.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
similarity index 97%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1000-mt76-mt7996-add-debug-tool.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
index 018c7b9..7179a65 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1000-mt76-mt7996-add-debug-tool.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1000-wifi-mt76-mt7996-add-debug-tool.patch
@@ -1,43 +1,119 @@
-From 9cf11ae2bfdf56babbdfe4fe03f61f492c06ce1a Mon Sep 17 00:00:00 2001
+From e7b3aa46df08dc89f0ed30c36d56ee4acf50d982 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Fri, 24 Mar 2023 14:02:32 +0800
-Subject: [PATCH 1000/1001] mt76: mt7996: add debug tool
+Subject: [PATCH 1000/1015] wifi: mt76: mt7996: add debug tool
 
 Change-Id: Ie10390b01f17db893dbfbf3221bf63a4bd1fe38f
 ---
  mt7996/Makefile      |    3 +
- mt7996/debugfs.c     |   31 +-
- mt7996/mcu.c         |    4 +
- mt7996/mt7996.h      |   15 +
- mt7996/mtk_debug.h   | 2166 ++++++++++++++++++++++++++++++++++++++
- mt7996/mtk_debugfs.c | 2344 ++++++++++++++++++++++++++++++++++++++++++
+ mt7996/coredump.c    |   10 +-
+ mt7996/coredump.h    |    7 +
+ mt7996/debugfs.c     |   29 +-
+ mt7996/mt7996.h      |   14 +
+ mt7996/mtk_debug.h   | 2165 ++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_debugfs.c | 2353 ++++++++++++++++++++++++++++++++++++++++++
  mt7996/mtk_mcu.c     |   18 +
  mt7996/mtk_mcu.h     |   16 +
  tools/fwlog.c        |   25 +-
- 9 files changed, 4606 insertions(+), 16 deletions(-)
+ 10 files changed, 4622 insertions(+), 18 deletions(-)
  create mode 100644 mt7996/mtk_debug.h
  create mode 100644 mt7996/mtk_debugfs.c
  create mode 100644 mt7996/mtk_mcu.c
  create mode 100644 mt7996/mtk_mcu.h
 
 diff --git a/mt7996/Makefile b/mt7996/Makefile
-index bed9efd6..9ef0b824 100644
+index 7c2514a6..df131869 100644
 --- a/mt7996/Makefile
 +++ b/mt7996/Makefile
-@@ -1,4 +1,5 @@
+@@ -1,5 +1,6 @@
  # SPDX-License-Identifier: ISC
+ EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
 +EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
  
  obj-$(CONFIG_MT7996E) += mt7996e.o
  
-@@ -8,3 +9,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
+@@ -9,3 +10,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
  mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
  
  mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
 +
 +mt7996e-y += mtk_debugfs.o mtk_mcu.o
+diff --git a/mt7996/coredump.c b/mt7996/coredump.c
+index 60b88085..a7f91b56 100644
+--- a/mt7996/coredump.c
++++ b/mt7996/coredump.c
+@@ -195,7 +195,7 @@ mt7996_coredump_fw_stack(struct mt7996_dev *dev, u8 type, struct mt7996_coredump
+ 	}
+ }
+ 
+-static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type)
++struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type, bool full_dump)
+ {
+ 	struct mt7996_crash_data *crash_data = dev->coredump.crash_data[type];
+ 	struct mt7996_coredump *dump;
+@@ -206,7 +206,7 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8
+ 
+ 	len = hdr_len;
+ 
+-	if (coredump_memdump && crash_data->memdump_buf_len)
++	if (full_dump && coredump_memdump && crash_data->memdump_buf_len)
+ 		len += sizeof(*dump_mem) + crash_data->memdump_buf_len;
+ 
+ 	sofar += hdr_len;
+@@ -248,6 +248,9 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8
+ 	mt7996_coredump_fw_state(dev, type, dump, &exception);
+ 	mt7996_coredump_fw_stack(dev, type, dump, exception);
+ 
++	if (!full_dump)
++		goto skip_dump_mem;
++
+ 	/* gather memory content */
+ 	dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
+ 	dump_mem->len = crash_data->memdump_buf_len;
+@@ -255,6 +258,7 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8
+ 		memcpy(dump_mem->data, crash_data->memdump_buf,
+ 		       crash_data->memdump_buf_len);
+ 
++skip_dump_mem:
+ 	mutex_unlock(&dev->dump_mutex);
+ 
+ 	return dump;
+@@ -264,7 +268,7 @@ int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
+ {
+ 	struct mt7996_coredump *dump;
+ 
+-	dump = mt7996_coredump_build(dev, type);
++	dump = mt7996_coredump_build(dev, type, true);
+ 	if (!dump) {
+ 		dev_warn(dev->mt76.dev, "no crash dump data found\n");
+ 		return -ENODATA;
+diff --git a/mt7996/coredump.h b/mt7996/coredump.h
+index 01ed3731..93cd84a0 100644
+--- a/mt7996/coredump.h
++++ b/mt7996/coredump.h
+@@ -75,6 +75,7 @@ struct mt7996_mem_region {
+ const struct mt7996_mem_region *
+ mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num);
+ struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type);
++struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type, bool full_dump);
+ int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type);
+ int mt7996_coredump_register(struct mt7996_dev *dev);
+ void mt7996_coredump_unregister(struct mt7996_dev *dev);
+@@ -92,6 +93,12 @@ static inline int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
+ 	return 0;
+ }
+ 
++static inline struct
++mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type, bool full_dump)
++{
++	return NULL;
++}
++
+ static inline struct
+ mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
+ {
 diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
-index 04220180..0bfded17 100644
+index ca4d615d..8a513f46 100644
 --- a/mt7996/debugfs.c
 +++ b/mt7996/debugfs.c
 @@ -301,6 +301,9 @@ mt7996_fw_debug_wm_set(void *data, u64 val)
@@ -76,22 +152,19 @@
  	return mt7996_fw_debug_wm_set(dev, dev->fw_debug_wm);
  }
  
-@@ -821,8 +830,13 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
- 					    mt7996_rdd_monitor);
- 	}
- 
--	if (phy == &dev->phy)
-+	if (phy == &dev->phy) {
+@@ -825,6 +834,11 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ 	if (phy == &dev->phy)
  		dev->debugfs_dir = dir;
+ 
 +#ifdef CONFIG_MTK_DEBUG
-+		debugfs_create_u16("wlan_idx", 0600, dir, &dev->wlan_idx);
-+		mt7996_mtk_init_debugfs(phy, dir);
++	debugfs_create_u16("wlan_idx", 0600, dir, &dev->wlan_idx);
++	mt7996_mtk_init_debugfs(phy, dir);
 +#endif
-+	}
- 
++
  	return 0;
  }
-@@ -836,6 +850,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
+ 
+@@ -837,6 +851,12 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
  	void *dest;
  
  	spin_lock_irqsave(&lock, flags);
@@ -104,7 +177,7 @@
  	dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
  	if (dest) {
  		*(u32 *)dest = hdrlen + len;
-@@ -868,9 +888,6 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
+@@ -869,9 +889,6 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
  		.msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR),
  	};
  
@@ -114,33 +187,11 @@
  	hdr.serial_id = cpu_to_le16(dev->fw_debug_seq++);
  	hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0)));
  	hdr.len = *(__le16 *)data;
-diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index f2bfbd8a..ef779cf9 100644
---- a/mt7996/mcu.c
-+++ b/mt7996/mcu.c
-@@ -2324,6 +2324,7 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
- 
- 	dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
- 		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
-+	memcpy(dev->dbg.patch_build_date, hdr->build_date, sizeof(dev->dbg.patch_build_date));
- 
- 	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
- 		struct mt7996_patch_sec *sec;
-@@ -2453,6 +2454,9 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
- 		hdr = (const struct mt7996_fw_trailer *)			\
- 				(fw->data + fw->size - sizeof(*hdr));		\
- 										\
-+		memcpy(dev->dbg.ram_build_date[MT7996_RAM_TYPE_##_type],	\
-+		       hdr->build_date,						\
-+		       sizeof(dev->dbg.ram_build_date[MT7996_RAM_TYPE_##_type]));\
- 		dev_info(dev->mt76.dev,						\
- 			 "%s Firmware Version: %.10s, Build Time: %.15s\n",	\
- 			 #_type, hdr->fw_ver, hdr->build_date);			\
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 9bf3bf1a..1ac54520 100644
+index 286fc1eb..6c76ec20 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -339,6 +339,17 @@ struct mt7996_dev {
+@@ -363,6 +363,16 @@ struct mt7996_dev {
  	u32 reg_l2_backup;
  
  	u8 wtbl_size_group;
@@ -148,8 +199,7 @@
 +#ifdef CONFIG_MTK_DEBUG
 +	u16 wlan_idx;
 +	struct {
-+		char patch_build_date[16];
-+		char ram_build_date[3][15];
++		u8 sku_disable;
 +		u32 fw_dbg_module;
 +		u8 fw_dbg_lv;
 +		u32 bcn_total_cnt[__MT_MAX_BAND];
@@ -158,7 +208,7 @@
  };
  
  enum {
-@@ -608,4 +619,8 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -659,4 +669,8 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  			    struct ieee80211_sta *sta, struct dentry *dir);
  #endif
  
@@ -169,10 +219,10 @@
  #endif
 diff --git a/mt7996/mtk_debug.h b/mt7996/mtk_debug.h
 new file mode 100644
-index 00000000..a48bac50
+index 00000000..eb40f9cb
 --- /dev/null
 +++ b/mt7996/mtk_debug.h
-@@ -0,0 +1,2166 @@
+@@ -0,0 +1,2165 @@
 +#ifndef __MTK_DEBUG_H
 +#define __MTK_DEBUG_H
 +
@@ -342,9 +392,8 @@
 +	u16 ring_size;
 +	char *const ring_info;
 +};
++
 +// HOST DMA
-+//#define CONN_INFRA_REMAPPING_OFFSET 0x64000000
-+//#define WF_WFDMA_HOST_DMA0_BASE (0x18024000 + CONN_INFRA_REMAPPING_OFFSET)
 +#define WF_WFDMA_HOST_DMA0_BASE                                0xd4000
 +
 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR                                   \
@@ -2341,10 +2390,10 @@
 +#endif
 diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
 new file mode 100644
-index 00000000..080f756e
+index 00000000..f04c300f
 --- /dev/null
 +++ b/mt7996/mtk_debugfs.c
-@@ -0,0 +1,2344 @@
+@@ -0,0 +1,2353 @@
 +// SPDX-License-Identifier: ISC
 +/*
 + * Copyright (C) 2023 MediaTek Inc.
@@ -2356,6 +2405,7 @@
 +#include "eeprom.h"
 +#include "mtk_debug.h"
 +#include "mtk_mcu.h"
++#include "coredump.h"
 +
 +#ifdef CONFIG_MTK_DEBUG
 +
@@ -2690,83 +2740,85 @@
 +	if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
 +		return 0;
 +
-+	seq_printf(s, "Rom Patch Build Time: %.16s\n", dev->dbg.patch_build_date);
-+	seq_printf(s, "WM Patch Build Time: %.15s\n",
-+		   dev->dbg.ram_build_date[MT7996_RAM_TYPE_WM]);
++	seq_printf(s, "Rom Patch Build Time: %.16s\n", dev->patch_build_date);
++	seq_printf(s, "WM Patch Build Time: %.15s, Mode: %s\n",
++		   dev->ram_build_date[MT7996_RAM_TYPE_WM],
++		   dev->testmode_enable ? "Testmode" : "Normal mode");
 +	seq_printf(s, "WA Patch Build Time: %.15s\n",
-+		   dev->dbg.ram_build_date[MT7996_RAM_TYPE_WA]);
++		   dev->ram_build_date[MT7996_RAM_TYPE_WA]);
 +	seq_printf(s, "DSP Patch Build Time: %.15s\n",
-+		   dev->dbg.ram_build_date[MT7996_RAM_TYPE_DSP]);
++		   dev->ram_build_date[MT7996_RAM_TYPE_DSP]);
 +	return 0;
 +}
 +
-+/* dma info dump */
-+const struct queue_desc mt7902_tx_ring_layout[] = {
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_ADDR,
-+	 .ring_size = 2048,
-+	 .ring_info = "band0 TXD"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL0_ADDR,
-+	 .ring_size = 2048,
-+	 .ring_info = "band1 TXD"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL0_ADDR,
-+	 .ring_size = 2048,
-+	 .ring_info = "band2 TXD"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_ADDR,
-+	 .ring_size = 128,
-+	 .ring_info = "FWDL"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_ADDR,
-+	 .ring_size = 256,
-+	 .ring_info = "cmd to WM"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL0_ADDR,
-+	 .ring_size = 256,
-+	 .ring_info = "cmd to WA"
++/* fw wm call trace info dump */
++void mt7996_show_lp_history(struct seq_file *s, u32 type)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt7996_crash_data *crash_data;
++	struct mt7996_coredump *dump;
++	u64 now = 0;
++	int i = 0;
++	u8 fw_type = !!type;
++
++	mutex_lock(&dev->dump_mutex);
++
++	crash_data = mt7996_coredump_new(dev, fw_type);
++	if (!crash_data) {
++		mutex_unlock(&dev->dump_mutex);
++		seq_printf(s, "the coredump is disable!\n");
++		return;
 +	}
-+};
++	mutex_unlock(&dev->dump_mutex);
 +
-+const struct queue_desc mt7902_rx_ring_layout[] = {
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR,
-+	 .ring_size = 1536,
-+	 .ring_info = "band0 RX data"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR,
-+	 .ring_size = 1536,
-+	 .ring_info = "band1 RX data"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL0_ADDR,
-+	 .ring_size = 1536,
-+	 .ring_info = "band2 RX data"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR,
-+	 .ring_size = 512,
-+	 .ring_info = "event from WM"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR,
-+	 .ring_size = 1024,
-+	 .ring_info = "event from WA"
-+	},
-+	{
-+	 .hw_desc_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR,
-+	 .ring_size = 1024,
-+	 .ring_info = "band0/1/2 tx free done"
-+	},
-+};
++	dump = mt7996_coredump_build(dev, fw_type, false);
++	if (!dump) {
++		seq_printf(s, "no call stack data found!\n");
++		return;
++	}
++
++	seq_printf(s, "\x1b[32m%s log output\x1b[0m\n", dump->fw_type);
++	seq_printf(s, "\x1b[32mfw status: %s\n", dump->fw_state);
++	mt7996_dump_version(s, NULL);
++	/* PC log */
++	now = jiffies;
++	for (i = 0; i < 10; i++)
++		seq_printf(s, "\tCurrent PC=%x\n", dump->pc_cur[i]);
 +
++	seq_printf(s, "PC log contorl=0x%x(T=%llu)(latest PC index = 0x%x)\n",
++		dump->pc_dbg_ctrl, now, dump->pc_cur_idx);
++	for (i = 0; i < 32; i++)
++		seq_printf(s, "\tPC log(%d)=0x%08x\n", i, dump->pc_stack[i]);
++
++	/* LR log */
++	now = jiffies;
++	seq_printf(s, "\nLR log contorl=0x%x(T=%llu)(latest LR index = 0x%x)\n",
++		dump->lr_dbg_ctrl, now, dump->lr_cur_idx);
++	for (i = 0; i < 32; i++)
++		seq_printf(s, "\tLR log(%d)=0x%08x\n", i, dump->lr_stack[i]);
++
++	vfree(dump);
++}
++
++static int mt7996_fw_wa_info_read(struct seq_file *s, void *data)
++{
++	seq_printf(s, "======[ShowPcLpHistory]======\n");
++	mt7996_show_lp_history(s, MT7996_RAM_TYPE_WA);
++	seq_printf(s, "======[End ShowPcLpHistory]==\n");
++
++	return 0;
++}
++
++static int mt7996_fw_wm_info_read(struct seq_file *s, void *data)
++{
++	seq_printf(s, "======[ShowPcLpHistory]======\n");
++	mt7996_show_lp_history(s, MT7996_RAM_TYPE_WM);
++	seq_printf(s, "======[End ShowPcLpHistory]==\n");
++
++	return 0;
++}
++
++/* dma info dump */
 +static void
 +dump_dma_tx_ring_info(struct seq_file *s, struct mt7996_dev *dev,  char *str1, char *str2, u32 ring_base)
 +{
@@ -4668,6 +4720,10 @@
 +	debugfs_create_file("fw_wa_set", 0600, dir, dev, &fops_wa_set);
 +	debugfs_create_devm_seqfile(dev->mt76.dev, "fw_version", dir,
 +				    mt7996_dump_version);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "fw_wa_info", dir,
++				    mt7996_fw_wa_info_read);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "fw_wm_info", dir,
++				    mt7996_fw_wm_info_read);
 +
 +	debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info0", dir,
 +				    mt7996_mibinfo_band0);
@@ -4685,6 +4741,8 @@
 +	debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
 +				    mt7996_wtbl_read);
 +
++	debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable);
++
 +	return 0;
 +}
 +
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1001-mt76-mt7996-add-txpower-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches-3.x/1001-mt76-mt7996-add-txpower-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch
index a9a371d..75fa826 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/1001-mt76-mt7996-add-txpower-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1001-wifi-mt76-mt7996-add-txpower-support.patch
@@ -1,7 +1,7 @@
-From 0169bc58ed8089fc7ca07d08a0ce90a02db4a3dd Mon Sep 17 00:00:00 2001
+From b729a28ee5895d921e8df1a371e114dee7724595 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Fri, 24 Mar 2023 23:35:30 +0800
-Subject: [PATCH 1001/1001] mt76: mt7996: add txpower support
+Subject: [PATCH 1001/1015] wifi: mt76: mt7996: add txpower support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Change-Id: Ic3e7b17f3664fa7f774137572f885359fa2ec93b
@@ -17,10 +17,10 @@
  8 files changed, 423 insertions(+), 5 deletions(-)
 
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 50f2227f..c8f65b98 100644
+index b81ed64c..be0a34ae 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
-@@ -280,3 +280,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
+@@ -293,3 +293,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
  
  	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
  }
@@ -59,10 +59,10 @@
 +	[SKU_EHT3x996_484] = 16,
 +};
 diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
-index 0f8f0cd8..54e180fb 100644
+index 9ea3667f..343e65e1 100644
 --- a/mt7996/eeprom.h
 +++ b/mt7996/eeprom.h
-@@ -72,4 +72,46 @@ mt7996_get_channel_group_6g(int channel)
+@@ -75,4 +75,46 @@ mt7996_get_channel_group_6g(int channel)
  	return DIV_ROUND_UP(channel - 29, 32);
  }
  
@@ -110,10 +110,10 @@
 +
  #endif
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index ebc62713..476e007b 100644
+index 549007f9..5d52b0b7 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -698,6 +698,7 @@ struct tx_power_ctrl {
+@@ -712,6 +712,7 @@ struct tx_power_ctrl {
  		bool ate_mode_enable;
  		bool percentage_ctrl_enable;
  		bool bf_backoff_enable;
@@ -121,7 +121,7 @@
  		u8 power_drop_level;
  	};
  	u8 band_idx;
-@@ -711,6 +712,7 @@ enum {
+@@ -725,6 +726,7 @@ enum {
  	UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
  	UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
  	UNI_TXPOWER_ATE_MODE_CTRL = 6,
@@ -130,31 +130,31 @@
  
  enum {
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 1ac54520..9bed13a1 100644
+index 6c76ec20..085307ab 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
-@@ -57,6 +57,8 @@
- #define MT7996_CRIT_TEMP		110
- #define MT7996_MAX_TEMP			120
+@@ -60,6 +60,8 @@
+ 
+ #define MT7996_BUILD_TIME_LEN		24
  
 +#define MT7996_SKU_RATE_NUM		417
 +
  struct mt7996_vif;
  struct mt7996_sta;
  struct mt7996_dfs_pulse;
-@@ -525,6 +527,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+@@ -563,6 +565,7 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
  void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
  void mt7996_mcu_exit(struct mt7996_dev *dev);
  int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
 +int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
+ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
  
- static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
- {
 diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
-index 080f756e..c05f8465 100644
+index f04c300f..2aee3ab0 100644
 --- a/mt7996/mtk_debugfs.c
 +++ b/mt7996/mtk_debugfs.c
-@@ -2296,6 +2296,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
+@@ -2299,6 +2299,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
  	return 0;
  }
  
@@ -387,7 +387,7 @@
  int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
  {
  	struct mt7996_dev *dev = phy->dev;
-@@ -2334,6 +2560,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+@@ -2341,6 +2567,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
  
  	debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir,
  				    mt7996_trinfo_read);
@@ -522,10 +522,10 @@
  #endif
  
 diff --git a/mt7996/regs.h b/mt7996/regs.h
-index d1d3d154..d01cc8c9 100644
+index 3a5914c4..6ef905a9 100644
 --- a/mt7996/regs.h
 +++ b/mt7996/regs.h
-@@ -557,15 +557,22 @@ enum base_rev {
+@@ -562,15 +562,22 @@ enum base_rev {
  
  #define MT_PCIE1_MAC_INT_ENABLE			MT_PCIE1_MAC(0x188)
  
@@ -552,7 +552,7 @@
  /* PHYRX CSD */
  #define MT_WF_PHYRX_CSD_BASE			0x83000000
  #define MT_WF_PHYRX_CSD(_band, _wf, ofs)	(MT_WF_PHYRX_CSD_BASE + \
-@@ -574,7 +581,7 @@ enum base_rev {
+@@ -579,7 +586,7 @@ enum base_rev {
  #define MT_WF_PHYRX_CSD_IRPI(_band, _wf)	MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
  
  /* PHYRX CSD BAND */
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
new file mode 100644
index 0000000..fe75034
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch
@@ -0,0 +1,292 @@
+From 55619fa44187b6ed841f94c2bedbc4779457e3f9 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Tue, 13 Dec 2022 15:17:43 +0800
+Subject: [PATCH 1002/1015] wifi: mt76: mt7996: add mu vendor command support
+
+Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
+---
+ mt7996/Makefile |  3 +-
+ mt7996/init.c   |  8 +++++
+ mt7996/mcu.c    | 37 +++++++++++++++++++---
+ mt7996/mcu.h    | 12 +++++++
+ mt7996/mt7996.h |  7 +++++
+ mt7996/vendor.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 22 +++++++++++++
+ 7 files changed, 167 insertions(+), 6 deletions(-)
+ create mode 100644 mt7996/vendor.c
+ create mode 100644 mt7996/vendor.h
+
+diff --git a/mt7996/Makefile b/mt7996/Makefile
+index df131869..8dbbc34c 100644
+--- a/mt7996/Makefile
++++ b/mt7996/Makefile
+@@ -1,11 +1,12 @@
+ # SPDX-License-Identifier: ISC
+ EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
+ EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
++EXTRA_CFLAGS += -DCONFIG_MTK_VENDOR
+ 
+ obj-$(CONFIG_MT7996E) += mt7996e.o
+ 
+ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
+-	     debugfs.o mmio.o
++	     debugfs.o mmio.o vendor.o
+ 
+ mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
+ 
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 96c4bb01..1d4359f0 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -579,6 +579,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	if (ret)
+ 		goto error;
+ 
++#ifdef CONFIG_MTK_VENDOR
++	mt7996_vendor_register(phy);
++#endif
++
+ 	ret = mt76_register_phy(mphy, true, mt76_rates,
+ 				ARRAY_SIZE(mt76_rates));
+ 	if (ret)
+@@ -1082,6 +1086,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	dev->mt76.test_ops = &mt7996_testmode_ops;
+ #endif
+ 
++#ifdef CONFIG_MTK_VENDOR
++	mt7996_vendor_register(&dev->phy);
++#endif
++
+ 	ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+ 				   ARRAY_SIZE(mt76_rates));
+ 	if (ret)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 58893348..91f3103a 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1158,6 +1158,8 @@ static void
+ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+ 			struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+ {
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct mt7996_phy *phy = mvif->phy;
+ 	struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
+ 	struct sta_rec_muru *muru;
+ 	struct tlv *tlv;
+@@ -1169,11 +1171,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+ 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
+ 
+ 	muru = (struct sta_rec_muru *)tlv;
+-	muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
+-			       vif->bss_conf.he_mu_beamformer ||
+-			       vif->bss_conf.vht_mu_beamformer ||
+-			       vif->bss_conf.vht_mu_beamformee;
+-	muru->cfg.ofdma_dl_en = true;
++	muru->cfg.mimo_dl_en = (vif->bss_conf.eht_mu_beamformer ||
++				vif->bss_conf.he_mu_beamformer ||
++				vif->bss_conf.vht_mu_beamformer ||
++				vif->bss_conf.vht_mu_beamformee) &&
++			       !!(phy->muru_onoff & MUMIMO_DL);
++	muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL);
++	muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL);
++	muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL);
+ 
+ 	if (sta->deflink.vht_cap.vht_supported)
+ 		muru->mimo_dl.vht_mu_bfee =
+@@ -4353,3 +4358,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+ 	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
+ 				 &req, sizeof(req), false);
+ }
++
++#ifdef CONFIG_MTK_VENDOR
++void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
++{
++	u8 mode, val;
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct mt7996_phy *phy =  mvif->phy;
++
++	mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data));
++	val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
++
++	switch (mode) {
++	case RATE_PARAM_AUTO_MU:
++		if (val < 0 || val > 15) {
++			printk("Wrong value! The value is between 0-15.\n");
++			break;
++		}
++		phy->muru_onoff = val;
++		break;
++	}
++}
++#endif
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 5d52b0b7..baffbcd7 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -568,8 +568,20 @@ enum {
+ 	RATE_PARAM_FIXED_MCS,
+ 	RATE_PARAM_FIXED_GI = 11,
+ 	RATE_PARAM_AUTO = 20,
++#ifdef CONFIG_MTK_VENDOR
++	RATE_PARAM_AUTO_MU = 32,
++#endif
+ };
+ 
++#define RATE_CFG_MODE	GENMASK(15, 8)
++#define RATE_CFG_VAL	GENMASK(7, 0)
++
++/* MURU */
++#define OFDMA_DL                       BIT(0)
++#define OFDMA_UL                       BIT(1)
++#define MUMIMO_DL                      BIT(2)
++#define MUMIMO_UL                      BIT(3)
++
+ enum {
+ 	BF_SOUNDING_ON = 1,
+ 	BF_HW_EN_UPDATE = 17,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 085307ab..b9f3dd8e 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -263,6 +263,8 @@ struct mt7996_phy {
+ 	u32 rx_ampdu_ts;
+ 	u32 ampdu_ref;
+ 
++	u8 muru_onoff;
++
+ 	struct mib_stats mib;
+ 	struct mt76_channel_state state_ts;
+ 
+@@ -672,6 +674,11 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 			    struct ieee80211_sta *sta, struct dentry *dir);
+ #endif
+ 
++#ifdef CONFIG_MTK_VENDOR
++void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
++void mt7996_vendor_register(struct mt7996_phy *phy);
++#endif
++
+ #ifdef CONFIG_MTK_DEBUG
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
+ #endif
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+new file mode 100644
+index 00000000..08ecc2b3
+--- /dev/null
++++ b/mt7996/vendor.c
+@@ -0,0 +1,84 @@
++// SPDX-License-Identifier: ISC
++/*
++ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
++ */
++
++#include <net/netlink.h>
++
++#include "mt7996.h"
++#include "mcu.h"
++#include "vendor.h"
++
++static const struct nla_policy
++mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
++	[MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
++};
++
++static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
++				 struct wireless_dev *wdev,
++				 const void *data,
++				 int data_len)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
++	int err;
++	u8 val8;
++	u32 val32 = 0;
++
++	err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len,
++			mu_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) {
++		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]);
++		val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) |
++			 FIELD_PREP(RATE_CFG_VAL, val8);
++		ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
++							   mt7996_set_wireless_vif, &val32);
++	}
++
++	return 0;
++}
++
++static int
++mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++			   struct sk_buff *skb, const void *data, int data_len,
++			   unsigned long *storage)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	int len = 0;
++
++	if (*storage == 1)
++		return -ENOENT;
++	*storage = 1;
++
++	if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff))
++		return -ENOMEM;
++	len += 1;
++
++	return len;
++}
++
++static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_MU_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7996_vendor_mu_ctrl,
++		.dumpit = mt7996_vendor_mu_ctrl_dump,
++		.policy = mu_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
++	},
++};
++
++void mt7996_vendor_register(struct mt7996_phy *phy)
++{
++	phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
++	phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
++}
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+new file mode 100644
+index 00000000..8ac3ba8e
+--- /dev/null
++++ b/mt7996/vendor.h
+@@ -0,0 +1,22 @@
++#ifndef __MT7996_VENDOR_H
++#define __MT7996_VENDOR_H
++
++#define MTK_NL80211_VENDOR_ID	0x0ce7
++
++enum mtk_nl80211_vendor_subcmds {
++	MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
++};
++
++enum mtk_vendor_attr_mu_ctrl {
++	MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
++	MTK_VENDOR_ATTR_MU_CTRL_DUMP,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_MU_CTRL,
++	MTK_VENDOR_ATTR_MU_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
++};
++
++#endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch
new file mode 100644
index 0000000..d83c3f9
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1003-wifi-mt76-mt7996-Add-air-monitor-support.patch
@@ -0,0 +1,565 @@
+From 2637da59e92d101889cf3680e57f0594c6b349ec Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Wed, 26 Apr 2023 04:40:05 +0800
+Subject: [PATCH 1003/1015] wifi: mt76: mt7996: Add air monitor support
+
+---
+ mt76_connac_mcu.h |   1 +
+ mt7996/mac.c      |   4 +
+ mt7996/main.c     |   4 +
+ mt7996/mt7996.h   |  35 +++++
+ mt7996/vendor.c   | 362 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h   |  39 +++++
+ 6 files changed, 445 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 4bb9508a..e62f17ad 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1206,6 +1206,7 @@ enum {
+ 	MCU_UNI_CMD_REG_ACCESS = 0x0d,
+ 	MCU_UNI_CMD_CHIP_CONFIG = 0x0e,
+ 	MCU_UNI_CMD_POWER_CTRL = 0x0f,
++	MCU_UNI_CMD_CFG_SMESH = 0x10,
+ 	MCU_UNI_CMD_RX_HDR_TRANS = 0x12,
+ 	MCU_UNI_CMD_SER = 0x13,
+ 	MCU_UNI_CMD_TWT = 0x14,
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 05269e7f..3dc5cdae 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -865,6 +865,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ 			if (ieee80211_has_a4(fc) && is_mesh && status->amsdu)
+ 				*qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+ 		}
++#ifdef CONFIG_MTK_VENDOR
++		if (phy->amnt_ctrl.enable && !ieee80211_is_beacon(fc))
++			mt7996_vendor_amnt_fill_rx(phy, skb);
++#endif
+ 	} else {
+ 		status->flag |= RX_FLAG_8023;
+ 	}
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 2ed66e6c..e5627c96 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -672,6 +672,10 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ 	mt7996_mac_wtbl_update(dev, idx,
+ 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+ 
++#ifdef CONFIG_MTK_VENDOR
++	mt7996_vendor_amnt_sta_remove(mvif->phy, sta);
++#endif
++
+ 	ret = mt7996_mcu_add_sta(dev, vif, sta, true);
+ 	if (ret)
+ 		return ret;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index b9f3dd8e..dc44edc1 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -235,6 +235,34 @@ enum {
+ 	SCS_ENABLE,
+ };
+ 
++#ifdef CONFIG_MTK_VENDOR
++#define MT7996_AIR_MONITOR_MAX_ENTRY	16
++#define MT7996_AIR_MONITOR_MAX_GROUP	(MT7996_AIR_MONITOR_MAX_ENTRY >> 1)
++
++struct mt7996_air_monitor_group {
++	bool enable;
++	bool used[2];
++};
++
++struct mt7996_air_monitor_entry {
++	bool enable;
++
++	u8 group_idx;
++	u8 group_used_idx;
++	u8 muar_idx;
++	u8 addr[ETH_ALEN];
++	u32 last_seen;
++	s8 rssi[4];
++	struct ieee80211_sta *sta;
++};
++
++struct mt7996_air_monitor_ctrl {
++	u8 enable;
++	struct mt7996_air_monitor_group group[MT7996_AIR_MONITOR_MAX_GROUP];
++	struct mt7996_air_monitor_entry entry[MT7996_AIR_MONITOR_MAX_ENTRY];
++};
++#endif
++
+ struct mt7996_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -285,6 +313,10 @@ struct mt7996_phy {
+ 		u8 spe_idx;
+ 	} test;
+ #endif
++#ifdef CONFIG_MTK_VENDOR
++	spinlock_t amnt_lock;
++	struct mt7996_air_monitor_ctrl amnt_ctrl;
++#endif
+ };
+ 
+ struct mt7996_dev {
+@@ -677,6 +709,9 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ #ifdef CONFIG_MTK_VENDOR
+ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
+ void mt7996_vendor_register(struct mt7996_phy *phy);
++void mt7996_vendor_amnt_fill_rx(struct mt7996_phy *phy, struct sk_buff *skb);
++int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
++				  struct ieee80211_sta *sta);
+ #endif
+ 
+ #ifdef CONFIG_MTK_DEBUG
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 08ecc2b3..8a021324 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -15,6 +15,32 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
+ 	[MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
+ };
+ 
++static const struct nla_policy
++amnt_ctrl_policy[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL] = {
++	[MTK_VENDOR_ATTR_AMNT_CTRL_SET] = {.type = NLA_NESTED },
++	[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP] = { .type = NLA_NESTED },
++};
++
++static const struct nla_policy
++amnt_set_policy[NUM_MTK_VENDOR_ATTRS_AMNT_SET] = {
++	[MTK_VENDOR_ATTR_AMNT_SET_INDEX] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_AMNT_SET_MACADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
++};
++
++static const struct nla_policy
++amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
++	[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX] = {.type = NLA_U8 },
++	[MTK_VENDOR_ATTR_AMNT_DUMP_LEN] = { .type = NLA_U8 },
++	[MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED },
++};
++
++struct mt7996_amnt_data {
++	u8 idx;
++	u8 addr[ETH_ALEN];
++	s8 rssi[4];
++	u32 last_seen;
++};
++
+ static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
+ 				 struct wireless_dev *wdev,
+ 				 const void *data,
+@@ -62,6 +88,328 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return len;
+ }
+ 
++void mt7996_vendor_amnt_fill_rx(struct mt7996_phy *phy, struct sk_buff *skb)
++{
++	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
++	struct mt7996_air_monitor_ctrl *ctrl = &phy->amnt_ctrl;
++	struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
++	__le16 fc = hdr->frame_control;
++	u8 addr[ETH_ALEN];
++	int i;
++
++	if (!ieee80211_has_fromds(fc))
++		ether_addr_copy(addr, hdr->addr2);
++	else if (ieee80211_has_tods(fc))
++		ether_addr_copy(addr, hdr->addr4);
++	else
++		ether_addr_copy(addr, hdr->addr3);
++
++	spin_lock_bh(&phy->amnt_lock);
++	for (i = 0; i < MT7996_AIR_MONITOR_MAX_ENTRY; i++) {
++		struct mt7996_air_monitor_entry *entry;
++
++		if (ether_addr_equal(addr, ctrl->entry[i].addr)) {
++			entry = &ctrl->entry[i];
++			entry->rssi[0] = status->chain_signal[0];
++			entry->rssi[1] = status->chain_signal[1];
++			entry->rssi[2] = status->chain_signal[2];
++			entry->rssi[3] = status->chain_signal[3];
++			entry->last_seen = jiffies;
++			break;
++		}
++	}
++	spin_unlock_bh(&phy->amnt_lock);
++}
++
++static int
++mt7996_vendor_smesh_ctrl(struct mt7996_phy *phy, u8 write,
++			 u8 enable, u8 *value)
++{
++#define UNI_CMD_SMESH_PARAM  0
++	struct mt7996_dev *dev = phy->dev;
++	struct smesh_param {
++		__le16 tag;
++		__le16 length;
++
++		u8 enable;
++		bool a2;
++		bool a1;
++		bool data;
++		bool mgnt;
++		bool ctrl;
++		u8 padding[2];
++	} req = {
++		.tag = cpu_to_le16(UNI_CMD_SMESH_PARAM),
++		.length = cpu_to_le16(sizeof(req) - 4),
++
++		.enable = enable,
++		.a2 = true,
++		.a1 = true,
++		.data = true,
++		.mgnt = false,
++		.ctrl = false,
++	};
++	struct smesh_param *res;
++	struct sk_buff *skb;
++	int ret = 0;
++
++	if (!value)
++		return -EINVAL;
++
++	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD(CFG_SMESH),
++					&req, sizeof(req), !write, &skb);
++
++	if (ret || write)
++		return ret;
++
++	res = (struct smesh_param *) skb->data;
++
++	*value = res->enable;
++
++	dev_kfree_skb(skb);
++
++	return 0;
++}
++
++static int
++mt7996_vendor_amnt_muar(struct mt7996_phy *phy, u8 muar_idx, u8 *addr)
++{
++#define UNI_CMD_MUAR_ENTRY  2
++	struct mt7996_dev *dev = phy->dev;
++	struct muar_entry {
++		__le16 tag;
++		__le16 length;
++
++		bool smesh;
++		u8 hw_bss_index;
++		u8 muar_idx;
++		u8 entry_add;
++		u8 mac_addr[6];
++		u8 padding[2];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_MUAR_ENTRY),
++		.length = cpu_to_le16(sizeof(req) - 4),
++
++		.smesh = true,
++		.hw_bss_index = phy != &dev->phy,
++		.muar_idx = muar_idx,
++		.entry_add = 1,
++	};
++
++	ether_addr_copy(req.mac_addr, addr);
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(REPT_MUAR), &req,
++				 sizeof(req), true);
++}
++
++static int
++mt7996_vendor_amnt_set_en(struct mt7996_phy *phy, u8 enable)
++{
++	u8 status;
++	int ret;
++
++	ret = mt7996_vendor_smesh_ctrl(phy, 0, enable, &status);
++	if (ret)
++		return ret;
++
++	if (status == enable)
++		return 0;
++
++	ret = mt7996_vendor_smesh_ctrl(phy, 1, enable, &status);
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
++static int
++mt7996_vendor_amnt_set_addr(struct mt7996_phy *phy, u8 index, u8 *addr)
++{
++	struct mt7996_air_monitor_ctrl *amnt_ctrl = &phy->amnt_ctrl;
++	struct mt7996_air_monitor_group *group;
++	struct mt7996_air_monitor_entry *entry;
++	int ret, i, j;
++
++	if (index >= MT7996_AIR_MONITOR_MAX_ENTRY)
++		return -1;
++
++	spin_lock_bh(&phy->amnt_lock);
++	entry = &amnt_ctrl->entry[index];
++	if (!is_zero_ether_addr(addr)) {
++		if (entry->enable == false) {
++			for (i = 0; i < MT7996_AIR_MONITOR_MAX_GROUP; i++) {
++				group = &(amnt_ctrl->group[i]);
++				if (group->used[0] == false)
++					j = 0;
++				else if (group->used[1] == false)
++					j = 1;
++				else
++					continue;
++
++				group->enable = true;
++				group->used[j] = true;
++				entry->enable = true;
++				entry->group_idx = i;
++				entry->group_used_idx = j;
++				entry->muar_idx = 32 + 4 * i + 2 * j;
++				break;
++			}
++		}
++	} else {
++		group = &(amnt_ctrl->group[entry->group_idx]);
++
++		group->used[entry->group_used_idx] = false;
++		if (group->used[0] == false && group->used[1] == false)
++			group->enable = false;
++
++		entry->enable = false;
++	}
++	ether_addr_copy(entry->addr, addr);
++	amnt_ctrl->enable &= ~(1 << entry->group_idx);
++	amnt_ctrl->enable |= entry->enable << entry->group_idx;
++	spin_unlock_bh(&phy->amnt_lock);
++
++	ret = mt7996_vendor_amnt_muar(phy, entry->muar_idx, addr);
++	if (ret)
++		return ret;
++
++	return mt7996_vendor_amnt_set_en(phy, amnt_ctrl->enable);
++}
++
++static int
++mt7966_vendor_amnt_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
++			const void *data, int data_len)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL];
++	struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_SET];
++	u8 index = 0;
++	u8 mac_addr[ETH_ALEN];
++	int err;
++
++	err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len,
++			amnt_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET])
++		return -EINVAL;
++
++	err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_SET_MAX,
++		tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET], amnt_set_policy, NULL);
++
++	if (!tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX] ||
++		!tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR])
++		return -EINVAL;
++
++	index = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX]);
++	memcpy(mac_addr, nla_data(tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR]), ETH_ALEN);
++
++	return mt7996_vendor_amnt_set_addr(phy, index, mac_addr);
++}
++
++int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
++				  struct ieee80211_sta *sta)
++{
++	u8 zero[ETH_ALEN] = {};
++	int i;
++
++	if (!phy->amnt_ctrl.enable)
++		return 0;
++
++	for (i = 0; i < MT7996_AIR_MONITOR_MAX_ENTRY; i++)
++		if (ether_addr_equal(sta->addr, phy->amnt_ctrl.entry[i].addr))
++			return mt7996_vendor_amnt_set_addr(phy, i, zero);
++	return 0;
++}
++
++static int
++mt7996_amnt_dump(struct mt7996_phy *phy, struct sk_buff *skb,
++		 u8 amnt_idx, int *attrtype)
++{
++	struct mt7996_air_monitor_entry *entry;
++	struct mt7996_amnt_data data;
++	u32 last_seen = 0;
++
++	spin_lock_bh(&phy->amnt_lock);
++	entry = &phy->amnt_ctrl.entry[amnt_idx];
++	if (entry->enable == 0) {
++		spin_unlock_bh(&phy->amnt_lock);
++		return 0;
++	}
++
++	last_seen = jiffies_to_msecs(jiffies - entry->last_seen);
++	ether_addr_copy(data.addr, entry->addr);
++	data.rssi[0] = entry->rssi[0];
++	data.rssi[1] = entry->rssi[1];
++	data.rssi[2] = entry->rssi[2];
++	data.rssi[3] = entry->rssi[3];
++	spin_unlock_bh(&phy->amnt_lock);
++
++	data.idx = amnt_idx;
++	data.last_seen = last_seen;
++
++	nla_put(skb, (*attrtype)++, sizeof(struct mt7996_amnt_data), &data);
++
++	return 1;
++}
++
++static int
++mt7966_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++			     struct sk_buff *skb, const void *data, int data_len,
++			     unsigned long *storage)
++{
++	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL];
++	struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP];
++	void *a, *b;
++	int err = 0, attrtype = 0, i, len = 0;
++	u8 amnt_idx;
++
++	if (*storage == 1)
++		return -ENOENT;
++	*storage = 1;
++
++	err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len,
++			amnt_ctrl_policy, NULL);
++	if (err)
++		return err;
++
++	if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP])
++		return -EINVAL;
++
++	err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_DUMP_MAX,
++			       tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP],
++			       amnt_dump_policy, NULL);
++	if (err)
++		return err;
++
++	if (!tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX])
++		return -EINVAL;
++
++	amnt_idx = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX]);
++
++	a = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_CTRL_DUMP);
++	b = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_DUMP_RESULT);
++
++	if (amnt_idx != 0xff) {
++		len += mt7996_amnt_dump(phy, skb, amnt_idx, &attrtype);
++	} else {
++		for (i = 0; i < MT7996_AIR_MONITOR_MAX_ENTRY; i++)
++			len += mt7996_amnt_dump(phy, skb, i, &attrtype);
++	}
++
++	nla_nest_end(skb, b);
++
++	nla_put_u8(skb, MTK_VENDOR_ATTR_AMNT_DUMP_LEN, len);
++
++	nla_nest_end(skb, a);
++
++	return len + 1;
++}
++
++
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+ 		.info = {
+@@ -75,10 +423,24 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = mu_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.doit = mt7966_vendor_amnt_ctrl,
++		.dumpit = mt7966_vendor_amnt_ctrl_dump,
++		.policy = amnt_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+ {
+ 	phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
+ 	phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
++
++	spin_lock_init(&phy->amnt_lock);
+ }
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 8ac3ba8e..2078cafa 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -4,6 +4,7 @@
+ #define MTK_NL80211_VENDOR_ID	0x0ce7
+ 
+ enum mtk_nl80211_vendor_subcmds {
++	MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
+ 	MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+ };
+ 
+@@ -19,4 +20,42 @@ enum mtk_vendor_attr_mu_ctrl {
+ 		NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
+ };
+ 
++enum mtk_vendor_attr_mnt_ctrl {
++	MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_AMNT_CTRL_SET,
++	MTK_VENDOR_ATTR_AMNT_CTRL_DUMP,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_AMNT_CTRL,
++	MTK_VENDOR_ATTR_AMNT_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_AMNT_CTRL - 1
++};
++
++enum mtk_vendor_attr_mnt_set {
++	MTK_VENDOR_ATTR_AMNT_SET_UNSPEC,
++
++	MTK_VENDOR_ATTR_AMNT_SET_INDEX,
++	MTK_VENDOR_ATTR_AMNT_SET_MACADDR,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_AMNT_SET,
++	MTK_VENDOR_ATTR_AMNT_SET_MAX =
++		NUM_MTK_VENDOR_ATTRS_AMNT_SET - 1
++};
++
++enum mtk_vendor_attr_mnt_dump {
++	MTK_VENDOR_ATTR_AMNT_DUMP_UNSPEC,
++
++	MTK_VENDOR_ATTR_AMNT_DUMP_INDEX,
++	MTK_VENDOR_ATTR_AMNT_DUMP_LEN,
++	MTK_VENDOR_ATTR_AMNT_DUMP_RESULT,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_AMNT_DUMP,
++	MTK_VENDOR_ATTR_AMNT_DUMP_MAX =
++		NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1
++};
++
++
+ #endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
new file mode 100644
index 0000000..50db576
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch
@@ -0,0 +1,27 @@
+From 75b684d04d569b5e83780d2296bed12d3785836c Mon Sep 17 00:00:00 2001
+From: mtk23510 <rudra.shahi@mediatek.com>
+Date: Fri, 24 Mar 2023 19:18:53 +0800
+Subject: [PATCH 1004/1015] wifi: mt76: mt7996: add driver support for wpa3 ocv
+ and bp mt76
+
+Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
+---
+ mt7996/init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 1d4359f0..40d610ae 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -373,6 +373,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+ 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+ 
++	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
++	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
+ 	if (!mdev->dev->of_node ||
+ 	    !of_property_read_bool(mdev->dev->of_node,
+ 				   "mediatek,disable-radar-background"))
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch
new file mode 100644
index 0000000..8eaf2d5
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1005-wifi-mt76-mt7996-add-U-NII-4-support.patch
@@ -0,0 +1,25 @@
+From 09b50cf201ede70688619366c31aa2ddd57d5cb2 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 31 Mar 2023 11:26:27 +0800
+Subject: [PATCH 1005/1015] wifi: mt76: mt7996: add U-NII-4 support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mac80211.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/mac80211.c b/mac80211.c
+index d1cdaee8..501325e9 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -76,6 +76,7 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
+ 	CHAN5G(165, 5825),
+ 	CHAN5G(169, 5845),
+ 	CHAN5G(173, 5865),
++	CHAN5G(177, 5885),
+ };
+ 
+ static const struct ieee80211_channel mt76_channels_6ghz[] = {
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
new file mode 100644
index 0000000..e185c11
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch
@@ -0,0 +1,898 @@
+From 47c64d6cac5ed78fab15cd4173ae8935605a3fca Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 31 Mar 2023 11:27:24 +0800
+Subject: [PATCH 1006/1015] wifi: mt76: testmode: add testmode pre-calibration
+ support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: If8a6cc02fa20e35f079c826e0571e8c04c3f9c7e
+---
+ mac80211.c        |  21 ---
+ mt76.h            |  22 +++
+ mt76_connac_mcu.h |   2 +
+ mt7996/eeprom.c   |  66 +++++++
+ mt7996/eeprom.h   |  47 +++++
+ mt7996/mcu.c      |   5 +
+ mt7996/mt7996.h   |   7 +
+ mt7996/testmode.c | 437 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/testmode.h |  20 ++-
+ testmode.c        |  12 ++
+ testmode.h        |   8 +
+ tools/fields.c    |   8 +
+ 12 files changed, 632 insertions(+), 23 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 501325e9..6430e6ee 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -7,27 +7,6 @@
+ #include <net/page_pool.h>
+ #include "mt76.h"
+ 
+-#define CHAN2G(_idx, _freq) {			\
+-	.band = NL80211_BAND_2GHZ,		\
+-	.center_freq = (_freq),			\
+-	.hw_value = (_idx),			\
+-	.max_power = 30,			\
+-}
+-
+-#define CHAN5G(_idx, _freq) {			\
+-	.band = NL80211_BAND_5GHZ,		\
+-	.center_freq = (_freq),			\
+-	.hw_value = (_idx),			\
+-	.max_power = 30,			\
+-}
+-
+-#define CHAN6G(_idx, _freq) {			\
+-	.band = NL80211_BAND_6GHZ,		\
+-	.center_freq = (_freq),			\
+-	.hw_value = (_idx),			\
+-	.max_power = 30,			\
+-}
+-
+ static const struct ieee80211_channel mt76_channels_2ghz[] = {
+ 	CHAN2G(1, 2412),
+ 	CHAN2G(2, 2417),
+diff --git a/mt76.h b/mt76.h
+index 31d5dc37..3341720c 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -18,6 +18,27 @@
+ #include "util.h"
+ #include "testmode.h"
+ 
++#define CHAN2G(_idx, _freq) {			\
++	.band = NL80211_BAND_2GHZ,		\
++	.center_freq = (_freq),			\
++	.hw_value = (_idx),			\
++	.max_power = 30,			\
++}
++
++#define CHAN5G(_idx, _freq) {			\
++	.band = NL80211_BAND_5GHZ,		\
++	.center_freq = (_freq),			\
++	.hw_value = (_idx),			\
++	.max_power = 30,			\
++}
++
++#define CHAN6G(_idx, _freq) {			\
++	.band = NL80211_BAND_6GHZ,		\
++	.center_freq = (_freq),			\
++	.hw_value = (_idx),			\
++	.max_power = 30,			\
++}
++
+ #define MT_MCU_RING_SIZE	32
+ #define MT_RX_BUF_SIZE		2048
+ #define MT_SKB_HEAD_LEN		256
+@@ -654,6 +675,7 @@ struct mt76_testmode_ops {
+ 	int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
+ 	void (*reset_rx_stats)(struct mt76_phy *phy);
+ 	void (*tx_stop)(struct mt76_phy *phy);
++	int (*dump_precal)(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type);
+ };
+ 
+ #define MT_TM_FW_RX_COUNT	BIT(0)
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index e62f17ad..262abf88 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1011,6 +1011,8 @@ enum {
+ 	MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
+ 	MCU_UNI_EVENT_RDD_REPORT = 0x11,
+ 	MCU_UNI_EVENT_THERMAL = 0x35,
++	MCU_UNI_EVENT_BF = 0x33,
++	MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
+ };
+ 
+ #define MCU_UNI_CMD_EVENT			BIT(1)
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index be0a34ae..60e98463 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -12,6 +12,42 @@ static bool testmode_enable;
+ module_param(testmode_enable, bool, 0644);
+ MODULE_PARM_DESC(testmode_enable, "Enable testmode");
+ 
++const struct ieee80211_channel dpd_2g_ch_list_bw20[] = {
++	CHAN2G(3, 2422),
++	CHAN2G(7, 2442),
++	CHAN2G(11, 2462)
++};
++
++const struct ieee80211_channel dpd_5g_ch_list_bw160[] = {
++	CHAN5G(50, 5250),
++	CHAN5G(114, 5570),
++	CHAN5G(163, 5815)
++};
++
++const struct ieee80211_channel dpd_6g_ch_list_bw160[] = {
++	CHAN6G(15, 6025),
++	CHAN6G(47, 6185),
++	CHAN6G(79, 6345),
++	CHAN6G(111, 6505),
++	CHAN6G(143, 6665),
++	CHAN6G(175, 6825),
++	CHAN6G(207, 6985)
++};
++
++const struct ieee80211_channel dpd_6g_ch_list_bw320[] = {
++	CHAN6G(31, 6105),
++	CHAN6G(63, 6265),
++	CHAN6G(95, 6425),
++	CHAN6G(127, 6585),
++	CHAN6G(159, 6745),
++	CHAN6G(191, 6905)
++};
++
++const u32 dpd_2g_bw20_ch_num = ARRAY_SIZE(dpd_2g_ch_list_bw20);
++const u32 dpd_5g_bw160_ch_num = ARRAY_SIZE(dpd_5g_ch_list_bw160);
++const u32 dpd_6g_bw160_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw160);
++const u32 dpd_6g_bw320_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw320);
++
+ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ {
+ 	u8 *eeprom = dev->mt76.eeprom.data;
+@@ -34,6 +70,36 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ 		return MT7996_EEPROM_DEFAULT;
+ }
+ 
++int
++mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band)
++{
++	/* handle different sku */
++	static const u8 band_to_idx[] = {
++		[NL80211_BAND_2GHZ] = MT_BAND0,
++		[NL80211_BAND_5GHZ] = MT_BAND1,
++		[NL80211_BAND_6GHZ] = MT_BAND2,
++	};
++	struct mt7996_phy *phy = __mt7996_phy(dev, band_to_idx[band]);
++	struct mt76_phy *mphy;
++	int dpd_size;
++
++	if (!phy)
++		return 0;
++
++	mphy = phy->mt76;
++
++	if (band == NL80211_BAND_2GHZ)
++		dpd_size = dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
++	else if (band == NL80211_BAND_5GHZ)
++		dpd_size = mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
++			   dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++	else
++		dpd_size = mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
++			   (dpd_6g_bw160_ch_num + dpd_6g_bw320_ch_num) * DPD_PER_CH_GT_BW20_SIZE;
++
++	return dpd_size;
++}
++
+ static int
+ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+ {
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 343e65e1..7ff290f4 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
+ 	MT_EE_MAC_ADDR =	0x004,
+ 	MT_EE_MAC_ADDR2 =	0x00a,
+ 	MT_EE_WIFI_CONF =	0x190,
++	MT_EE_DO_PRE_CAL =	0x1a5,
+ 	MT_EE_TESTMODE_EN =	0x1af,
+ 	MT_EE_MAC_ADDR3 =	0x2c0,
+ 	MT_EE_RATE_DELTA_2G =	0x1400,
+@@ -31,6 +32,52 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CONF1_BAND_SEL		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF2_BAND_SEL		GENMASK(2, 0)
+ 
++#define MT_EE_WIFI_CAL_GROUP_2G			BIT(0)
++#define MT_EE_WIFI_CAL_GROUP_5G			BIT(1)
++#define MT_EE_WIFI_CAL_GROUP_6G			BIT(2)
++#define MT_EE_WIFI_CAL_GROUP			GENMASK(2, 0)
++#define MT_EE_WIFI_CAL_DPD_2G			BIT(3)
++#define MT_EE_WIFI_CAL_DPD_5G			BIT(4)
++#define MT_EE_WIFI_CAL_DPD_6G			BIT(5)
++#define MT_EE_WIFI_CAL_DPD			GENMASK(5, 3)
++
++#define MT_EE_CAL_UNIT				1024
++#define MT_EE_CAL_GROUP_SIZE_2G			(4 * MT_EE_CAL_UNIT)
++#define MT_EE_CAL_GROUP_SIZE_5G			(45 * MT_EE_CAL_UNIT)
++#define MT_EE_CAL_GROUP_SIZE_6G			(125 * MT_EE_CAL_UNIT)
++#define MT_EE_CAL_ADCDCOC_SIZE_2G		(4 * 4)
++#define MT_EE_CAL_ADCDCOC_SIZE_5G		(4 * 4)
++#define MT_EE_CAL_ADCDCOC_SIZE_6G		(4 * 5)
++#define MT_EE_CAL_GROUP_SIZE			(MT_EE_CAL_GROUP_SIZE_2G + \
++						 MT_EE_CAL_GROUP_SIZE_5G + \
++						 MT_EE_CAL_GROUP_SIZE_6G + \
++						 MT_EE_CAL_ADCDCOC_SIZE_2G + \
++						 MT_EE_CAL_ADCDCOC_SIZE_5G + \
++						 MT_EE_CAL_ADCDCOC_SIZE_6G)
++
++#define DPD_PER_CH_LEGACY_SIZE			(4 * MT_EE_CAL_UNIT)
++#define DPD_PER_CH_MEM_SIZE			(13 * MT_EE_CAL_UNIT)
++#define DPD_PER_CH_OTFG0_SIZE			(2 * MT_EE_CAL_UNIT)
++#define DPD_PER_CH_BW20_SIZE			(DPD_PER_CH_LEGACY_SIZE + DPD_PER_CH_OTFG0_SIZE)
++#define DPD_PER_CH_GT_BW20_SIZE			(DPD_PER_CH_MEM_SIZE + DPD_PER_CH_OTFG0_SIZE)
++#define MT_EE_CAL_DPD_SIZE			(780 * MT_EE_CAL_UNIT)
++
++extern const struct ieee80211_channel dpd_2g_ch_list_bw20[];
++extern const u32 dpd_2g_bw20_ch_num;
++extern const struct ieee80211_channel dpd_5g_ch_list_bw160[];
++extern const u32 dpd_5g_bw160_ch_num;
++extern const struct ieee80211_channel dpd_6g_ch_list_bw160[];
++extern const u32 dpd_6g_bw160_ch_num;
++extern const struct ieee80211_channel dpd_6g_ch_list_bw320[];
++extern const u32 dpd_6g_bw320_ch_num;
++
++#define RF_DPD_FLAT_CAL				BIT(28)
++#define RF_PRE_CAL				BIT(29)
++#define RF_DPD_FLAT_5G_CAL			GENMASK(29, 28)
++#define RF_DPD_FLAT_5G_MEM_CAL			(BIT(30) | BIT(28))
++#define RF_DPD_FLAT_6G_CAL			GENMASK(30, 28)
++#define RF_DPD_FLAT_6G_MEM_CAL			(BIT(31) | BIT(28))
++
+ #define MT_EE_WIFI_CONF1_TX_PATH_BAND0		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF2_TX_PATH_BAND1		GENMASK(2, 0)
+ #define MT_EE_WIFI_CONF2_TX_PATH_BAND2		GENMASK(5, 3)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 91f3103a..1fb7bae1 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -523,6 +523,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	case MCU_UNI_EVENT_THERMAL:
+ 		mt7996_mcu_rx_thermal_notify(dev, skb);
+ 		break;
++#ifdef CONFIG_NL80211_TESTMODE
++	case MCU_UNI_EVENT_TESTMODE_CTRL:
++		mt7996_tm_rf_test_event(dev, skb);
++		break;
++#endif
+ 	default:
+ 		break;
+ 	}
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index dc44edc1..9ab86eaf 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -390,6 +390,9 @@ struct mt7996_dev {
+ 	struct dentry *debugfs_dir;
+ 	struct rchan *relay_fwlog;
+ 
++	void *cal;
++	u32 cur_prek_offset;
++
+ 	struct {
+ 		u8 table_mask;
+ 		u8 n_agrt;
+@@ -522,6 +525,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
+ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
+ 				   struct ieee80211_channel *chan);
+ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
++int mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band);
+ int mt7996_dma_init(struct mt7996_dev *dev);
+ void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+@@ -602,6 +606,9 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
+ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
++#ifdef CONFIG_NL80211_TESTMODE
++void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
++#endif
+ 
+ static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
+ {
+diff --git a/mt7996/testmode.c b/mt7996/testmode.c
+index 43eca4ef..7d36902e 100644
+--- a/mt7996/testmode.c
++++ b/mt7996/testmode.c
+@@ -7,6 +7,8 @@
+ #include "mac.h"
+ #include "mcu.h"
+ #include "testmode.h"
++#include "eeprom.h"
++#include "mtk_mcu.h"
+ 
+ enum {
+ 	TM_CHANGED_TXPOWER,
+@@ -397,6 +399,436 @@ mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
+ 	}
+ }
+ 
++static int
++mt7996_tm_group_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
++{
++	u8 *eeprom;
++	u32 i, group_size, dpd_size, size, offs, *pre_cal;
++	int ret = 0;
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_dev *mdev = &dev->mt76;
++	struct mt7996_tm_req req = {
++		.rf_test = {
++			.tag = cpu_to_le16(UNI_RF_TEST_CTRL),
++			.len = cpu_to_le16(sizeof(req.rf_test)),
++			.action = RF_ACTION_IN_RF_TEST,
++			.icap_len = RF_TEST_ICAP_LEN,
++			.op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
++			.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL),
++			.op.rf.param.cal_param.band_idx = phy->mt76->band_idx,
++		},
++	};
++
++	if (!dev->flash_mode) {
++		dev_err(dev->mt76.dev, "Currently not in FLASH or BIN FILE mode, return!\n");
++		return -EOPNOTSUPP;
++	}
++
++	eeprom = mdev->eeprom.data;
++	dev->cur_prek_offset = 0;
++	group_size = MT_EE_CAL_GROUP_SIZE;
++	dpd_size = MT_EE_CAL_DPD_SIZE;
++	size = group_size + dpd_size;
++	offs = MT_EE_DO_PRE_CAL;
++
++	switch (state) {
++	case MT76_TM_STATE_GROUP_PREK:
++		if (!dev->cal) {
++			dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++			if (!dev->cal)
++				return -ENOMEM;
++		}
++
++		ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), &req,
++					sizeof(req), false);
++		wait_event_timeout(mdev->mcu.wait, dev->cur_prek_offset == group_size,
++				   30 * HZ);
++
++		if (ret) {
++			dev_err(dev->mt76.dev, "Group Pre-cal: mcu send msg failed!\n");
++			return ret;
++		}
++
++		if (!ret)
++			eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
++		break;
++	case MT76_TM_STATE_GROUP_PREK_DUMP:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal) {
++			dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
++			return ret;
++		}
++		dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
++		for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
++			dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
++				 i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
++				 pre_cal[i + 2], pre_cal[i + 3]);
++		}
++		break;
++	case MT76_TM_STATE_GROUP_PREK_CLEAN:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal)
++			return ret;
++		memset(pre_cal, 0, group_size);
++		eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return ret;
++}
++
++static int
++mt7996_tm_dpd_prek_send_req(struct mt7996_phy *phy, struct mt7996_tm_req *req,
++			    const struct ieee80211_channel *chan_list, u32 channel_size,
++			    enum nl80211_chan_width width, u32 func_data)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_phy *mphy = phy->mt76;
++	struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
++	struct ieee80211_channel chan_backup;
++	int i, ret;
++
++	if (!chan_list)
++		return -EOPNOTSUPP;
++
++	req->rf_test.op.rf.param.cal_param.func_data = cpu_to_le32(func_data);
++
++	memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
++	memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
++
++	for (i = 0; i < channel_size; i++) {
++		memcpy(chandef->chan, &chan_list[i], sizeof(struct ieee80211_channel));
++		chandef->width = width;
++
++		/* set channel switch reason */
++		mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
++		mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
++
++		ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), req,
++					sizeof(*req), false);
++		if (ret) {
++			dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
++			goto out;
++		}
++	}
++
++out:
++	mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
++	memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
++	memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
++	mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
++
++	return ret;
++}
++
++static int
++mt7996_tm_dpd_prek(struct mt7996_phy *phy, enum mt76_testmode_state state)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_dev *mdev = &dev->mt76;
++	struct mt76_phy *mphy = phy->mt76;
++	struct mt7996_tm_req req = {
++		.rf_test = {
++			.tag = cpu_to_le16(UNI_RF_TEST_CTRL),
++			.len = cpu_to_le16(sizeof(req.rf_test)),
++			.action = RF_ACTION_IN_RF_TEST,
++			.icap_len = RF_TEST_ICAP_LEN,
++			.op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
++			.op.rf.param.cal_param.band_idx = phy->mt76->band_idx,
++		},
++	};
++	u32 i, j, group_size, dpd_size, size, offs, *pre_cal;
++	u32 wait_on_prek_offset = 0;
++	u8 do_precal, *eeprom;
++	int ret = 0;
++
++	if (!dev->flash_mode) {
++		dev_err(dev->mt76.dev, "Currently not in FLASH or BIN FILE mode, return!\n");
++		return -EOPNOTSUPP;
++	}
++
++	eeprom = mdev->eeprom.data;
++	dev->cur_prek_offset = 0;
++	group_size = MT_EE_CAL_GROUP_SIZE;
++	dpd_size = MT_EE_CAL_DPD_SIZE;
++	size = group_size + dpd_size;
++	offs = MT_EE_DO_PRE_CAL;
++
++	if (!dev->cal && state < MT76_TM_STATE_DPD_DUMP) {
++		dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++		if (!dev->cal)
++			return -ENOMEM;
++	}
++
++	switch (state) {
++	case MT76_TM_STATE_DPD_2G:
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_2g_ch_list_bw20,
++						  dpd_2g_bw20_ch_num,
++						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_CAL);
++		wait_on_prek_offset += dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		do_precal = MT_EE_WIFI_CAL_DPD_2G;
++		break;
++	case MT76_TM_STATE_DPD_5G:
++		/* 5g channel bw20 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, mphy->sband_5g.sband.channels,
++						  mphy->sband_5g.sband.n_channels,
++						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_5G_CAL);
++		if (ret)
++			return ret;
++		wait_on_prek_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		/* 5g channel bw160 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_5g_ch_list_bw160,
++						  dpd_5g_bw160_ch_num,
++						  NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_5G_MEM_CAL);
++		wait_on_prek_offset += dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		do_precal = MT_EE_WIFI_CAL_DPD_5G;
++		break;
++	case MT76_TM_STATE_DPD_6G:
++		/* 6g channel bw20 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, mphy->sband_6g.sband.channels,
++						  mphy->sband_6g.sband.n_channels,
++						  NL80211_CHAN_WIDTH_20, RF_DPD_FLAT_6G_CAL);
++		if (ret)
++			return ret;
++		wait_on_prek_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		/* 6g channel bw160 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw160,
++						  dpd_6g_bw160_ch_num,
++						  NL80211_CHAN_WIDTH_160, RF_DPD_FLAT_6G_MEM_CAL);
++		if (ret)
++			return ret;
++		wait_on_prek_offset += dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		/* 6g channel bw320 calibration */
++		ret = mt7996_tm_dpd_prek_send_req(phy, &req, dpd_6g_ch_list_bw320,
++						  dpd_6g_bw320_ch_num,
++						  NL80211_CHAN_WIDTH_320, RF_DPD_FLAT_6G_MEM_CAL);
++		wait_on_prek_offset += dpd_6g_bw320_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++		wait_event_timeout(mdev->mcu.wait,
++				   dev->cur_prek_offset == wait_on_prek_offset, 30 * HZ);
++
++		do_precal = MT_EE_WIFI_CAL_DPD_6G;
++		break;
++	case MT76_TM_STATE_DPD_DUMP:
++		if (!dev->cal) {
++			dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
++			return ret;
++		}
++		pre_cal = (u32 *)dev->cal;
++		dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
++		for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
++			j = i + (group_size / sizeof(u32));
++			dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
++				 j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
++				 pre_cal[j + 2], pre_cal[j + 3]);
++		}
++		return 0;
++	case MT76_TM_STATE_DPD_CLEAN:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal)
++			return ret;
++		memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
++		do_precal = MT_EE_WIFI_CAL_DPD;
++		eeprom[offs] &= ~do_precal;
++		return 0;
++	default:
++		return -EINVAL;
++	}
++
++	if (!ret)
++		eeprom[offs] |= do_precal;
++
++	return ret;
++}
++
++static int
++mt7996_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
++{
++#define DPD_PER_CHAN_SIZE_MASK		GENMASK(31, 30)
++#define DPD_2G_RATIO_MASK		GENMASK(29, 20)
++#define DPD_5G_RATIO_MASK		GENMASK(19, 10)
++#define DPD_6G_RATIO_MASK		GENMASK(9, 0)
++	struct mt7996_phy *phy = mphy->priv;
++	struct mt7996_dev *dev = phy->dev;
++	u32 i, group_size, dpd_size, total_size, size, dpd_info = 0;
++	u32 dpd_size_2g, dpd_size_5g, dpd_size_6g;
++	u32 base, offs, transmit_size = 1000;
++	u8 *pre_cal, *eeprom;
++	void *precal;
++	enum prek_ops {
++		PREK_GET_INFO,
++		PREK_SYNC_ALL,
++		PREK_SYNC_GROUP,
++		PREK_SYNC_DPD_2G,
++		PREK_SYNC_DPD_5G,
++		PREK_SYNC_DPD_6G,
++		PREK_CLEAN_GROUP,
++		PREK_CLEAN_DPD,
++	};
++
++	if (!dev->cal) {
++		dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
++		return 0;
++	}
++
++	group_size = MT_EE_CAL_GROUP_SIZE;
++	dpd_size = MT_EE_CAL_DPD_SIZE;
++	total_size = group_size + dpd_size;
++	pre_cal = dev->cal;
++	eeprom = dev->mt76.eeprom.data;
++	offs = MT_EE_DO_PRE_CAL;
++
++	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
++	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
++	dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
++
++	switch (type) {
++	case PREK_SYNC_ALL:
++		base = 0;
++		size = total_size;
++		break;
++	case PREK_SYNC_GROUP:
++		base = 0;
++		size = group_size;
++		break;
++	case PREK_SYNC_DPD_2G:
++		base = group_size;
++		size = dpd_size_2g;
++		break;
++	case PREK_SYNC_DPD_5G:
++		base = group_size + dpd_size_2g;
++		size = dpd_size_5g;
++		break;
++	case PREK_SYNC_DPD_6G:
++		base = group_size + dpd_size_2g + dpd_size_5g;
++		size = dpd_size_6g;
++		break;
++	case PREK_GET_INFO:
++		break;
++	default:
++		return 0;
++	}
++
++	if (!flag) {
++		if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
++			dpd_info |= u32_encode_bits(1, DPD_PER_CHAN_SIZE_MASK) |
++				    u32_encode_bits(dpd_size_2g / MT_EE_CAL_UNIT,
++						    DPD_2G_RATIO_MASK) |
++				    u32_encode_bits(dpd_size_5g / MT_EE_CAL_UNIT,
++						    DPD_5G_RATIO_MASK) |
++				    u32_encode_bits(dpd_size_6g / MT_EE_CAL_UNIT,
++						    DPD_6G_RATIO_MASK);
++		}
++		dev->cur_prek_offset = 0;
++		precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
++		if (!precal)
++			return -ENOMEM;
++		nla_put_u32(msg, 0, group_size);
++		nla_put_u32(msg, 1, dpd_size);
++		nla_put_u32(msg, 2, dpd_info);
++		nla_put_u32(msg, 3, transmit_size);
++		nla_put_u32(msg, 4, eeprom[offs]);
++		nla_nest_end(msg, precal);
++	} else {
++		precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
++		if (!precal)
++			return -ENOMEM;
++
++		transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
++				transmit_size : (size - dev->cur_prek_offset);
++		for (i = 0; i < transmit_size; i++) {
++			if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
++				return -ENOMEM;
++		}
++		dev->cur_prek_offset += transmit_size;
++
++		nla_nest_end(msg, precal);
++	}
++
++	return 0;
++}
++
++static void
++mt7996_tm_re_cal_event(struct mt7996_dev *dev, struct mt7996_tm_rf_test_result *result,
++		       struct mt7996_tm_rf_test_data *data)
++{
++	u32 base, dpd_size_2g, dpd_size_5g, dpd_size_6g, cal_idx, cal_type, len = 0;
++	u8 *pre_cal;
++
++	pre_cal = dev->cal;
++	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
++	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
++	dpd_size_6g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_6GHZ);
++
++	cal_idx = le32_to_cpu(data->cal_idx);
++	cal_type = le32_to_cpu(data->cal_type);
++	len = le32_to_cpu(result->payload_length);
++	len = len - sizeof(struct mt7996_tm_rf_test_data);
++
++	switch (cal_type) {
++	case RF_PRE_CAL:
++		base = 0;
++		break;
++	case RF_DPD_FLAT_CAL:
++		base = MT_EE_CAL_GROUP_SIZE;
++		break;
++	case RF_DPD_FLAT_5G_CAL:
++	case RF_DPD_FLAT_5G_MEM_CAL:
++		base = MT_EE_CAL_GROUP_SIZE + dpd_size_2g;
++		break;
++	case RF_DPD_FLAT_6G_CAL:
++	case RF_DPD_FLAT_6G_MEM_CAL:
++		base = MT_EE_CAL_GROUP_SIZE + dpd_size_2g + dpd_size_5g;
++		break;
++	default:
++		dev_info(dev->mt76.dev, "Unknown calibration type!\n");
++		return;
++	}
++	pre_cal += (base + dev->cur_prek_offset);
++
++	memcpy(pre_cal, data->cal_data, len);
++	dev->cur_prek_offset += len;
++}
++
++void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++	struct mt7996_tm_event *event;
++	struct mt7996_tm_rf_test_result *result;
++	struct mt7996_tm_rf_test_data *data;
++	static u32 event_type;
++
++	skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
++	event = (struct mt7996_tm_event *)skb->data;
++	result = (struct mt7996_tm_rf_test_result *)&event->result;
++	data = (struct mt7996_tm_rf_test_data *)result->data;
++
++	event_type = le32_to_cpu(result->func_idx);
++
++	switch (event_type) {
++	case RF_TEST_RE_CAL:
++		mt7996_tm_re_cal_event(dev, result, data);
++		break;
++	default:
++		break;
++	}
++}
++
+ static void
+ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+ {
+@@ -447,6 +879,10 @@ mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ 	else if (prev_state == MT76_TM_STATE_OFF ||
+ 		 state == MT76_TM_STATE_OFF)
+ 		mt7996_tm_init(phy, !(state == MT76_TM_STATE_OFF));
++	else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
++		return mt7996_tm_group_prek(phy, state);
++	else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
++		return mt7996_tm_dpd_prek(phy, state);
+ 
+ 	if ((state == MT76_TM_STATE_IDLE &&
+ 	     prev_state == MT76_TM_STATE_OFF) ||
+@@ -655,4 +1091,5 @@ const struct mt76_testmode_ops mt7996_testmode_ops = {
+ 	.dump_stats = mt7996_tm_dump_stats,
+ 	.reset_rx_stats = mt7996_tm_reset_trx_stats,
+ 	.tx_stop = mt7996_tm_tx_stop,
++	.dump_precal = mt7996_tm_dump_precal,
+ };
+diff --git a/mt7996/testmode.h b/mt7996/testmode.h
+index f00e51f4..778c9bc6 100644
+--- a/mt7996/testmode.h
++++ b/mt7996/testmode.h
+@@ -34,6 +34,12 @@ enum bw_mapping_method {
+ 	NUM_BW_MAP,
+ };
+ 
++struct tm_cal_param {
++	__le32 func_data;
++	u8 band_idx;
++	u8 rsv[3];
++};
++
+ struct mt7996_tm_rf_test {
+ 	__le16 tag;
+ 	__le16 len;
+@@ -50,7 +56,7 @@ struct mt7996_tm_rf_test {
+ 			union {
+ 				__le32 func_data;
+ 				__le32 cal_dump;
+-
++				struct tm_cal_param cal_param;
+ 				u8 _pad[80];
+ 			} param;
+ 		} rf;
+@@ -63,10 +69,16 @@ struct mt7996_tm_req {
+ 	struct mt7996_tm_rf_test rf_test;
+ } __packed;
+ 
++struct mt7996_tm_rf_test_data {
++	__le32 cal_idx;
++	__le32 cal_type;
++	u8 cal_data[0];
++} __packed;
++
+ struct mt7996_tm_rf_test_result {
+ 	__le32 func_idx;
+ 	__le32 payload_length;
+-	u8 event[0];
++	u8 data[0];
+ };
+ 
+ struct mt7996_tm_event {
+@@ -77,6 +89,8 @@ struct mt7996_tm_event {
+ 	struct mt7996_tm_rf_test_result result;
+ } __packed;
+ 
++#define RF_TEST_RE_CAL		0x01
++
+ enum {
+ 	RF_ACTION_SWITCH_TO_RF_TEST,
+ 	RF_ACTION_IN_RF_TEST,
+@@ -84,6 +98,8 @@ enum {
+ 	RF_ACTION_GET,
+ };
+ 
++#define RF_TEST_ICAP_LEN	120
++
+ enum {
+ 	RF_OPER_NORMAL,
+ 	RF_OPER_RF_TEST,
+diff --git a/testmode.c b/testmode.c
+index fc68c2af..74bb26fa 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -626,6 +626,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 
+ 	mutex_lock(&dev->mutex);
+ 
++	if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
++		int flag, type;
++
++		err = -EINVAL;
++		flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
++		type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
++		if (dev->test_ops->dump_precal)
++			err = dev->test_ops->dump_precal(phy, msg, flag, type);
++
++		goto out;
++	}
++
+ 	if (tb[MT76_TM_ATTR_STATS]) {
+ 		err = -EINVAL;
+ 
+diff --git a/testmode.h b/testmode.h
+index 8d0b9702..0c3b1393 100644
+--- a/testmode.h
++++ b/testmode.h
+@@ -215,6 +215,14 @@ enum mt76_testmode_state {
+ 	MT76_TM_STATE_TX_FRAMES,
+ 	MT76_TM_STATE_RX_FRAMES,
+ 	MT76_TM_STATE_TX_CONT,
++	MT76_TM_STATE_GROUP_PREK,
++	MT76_TM_STATE_GROUP_PREK_DUMP,
++	MT76_TM_STATE_GROUP_PREK_CLEAN,
++	MT76_TM_STATE_DPD_2G,
++	MT76_TM_STATE_DPD_5G,
++	MT76_TM_STATE_DPD_6G,
++	MT76_TM_STATE_DPD_DUMP,
++	MT76_TM_STATE_DPD_CLEAN,
+ 	MT76_TM_STATE_ON,
+ 
+ 	/* keep last */
+diff --git a/tools/fields.c b/tools/fields.c
+index e5cf7c53..b22b3fc8 100644
+--- a/tools/fields.c
++++ b/tools/fields.c
+@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
+ 	[MT76_TM_STATE_TX_FRAMES] = "tx_frames",
+ 	[MT76_TM_STATE_RX_FRAMES] = "rx_frames",
+ 	[MT76_TM_STATE_TX_CONT] = "tx_cont",
++	[MT76_TM_STATE_GROUP_PREK] = "group_prek",
++	[MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
++	[MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
++	[MT76_TM_STATE_DPD_2G] = "dpd_2g",
++	[MT76_TM_STATE_DPD_5G] = "dpd_5g",
++	[MT76_TM_STATE_DPD_6G] = "dpd_6g",
++	[MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
++	[MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
+ };
+ 
+ static const char * const testmode_tx_mode[] = {
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch
new file mode 100644
index 0000000..549344f
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1007-wifi-mt76-mt7996-add-binfile-mode-support.patch
@@ -0,0 +1,260 @@
+From 2cf8a9517919b39318eb1e878ca69418a499126a Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 31 Mar 2023 11:36:34 +0800
+Subject: [PATCH 1007/1015] wifi: mt76: mt7996: add binfile mode support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ eeprom.c             | 20 ++++++++++++++++++++
+ mt76.h               |  3 +++
+ mt7996/eeprom.c      | 42 +++++++++++++++++++++++++++++++++++++++---
+ mt7996/eeprom.h      |  7 +++++++
+ mt7996/mt7996.h      |  3 +++
+ mt7996/mtk_debugfs.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 112 insertions(+), 3 deletions(-)
+
+diff --git a/eeprom.c b/eeprom.c
+index aa889258..412740f0 100644
+--- a/eeprom.c
++++ b/eeprom.c
+@@ -104,6 +104,26 @@ out_put_node:
+ }
+ EXPORT_SYMBOL_GPL(mt76_get_of_eeprom);
+ 
++bool mt76_check_bin_file_mode(struct mt76_dev *dev)
++{
++	struct device_node *np = dev->dev->of_node;
++	const char *bin_file_name = NULL;
++
++	if (!np)
++		return false;
++
++	of_property_read_string(np, "bin_file_name", &bin_file_name);
++
++	dev->bin_file_name = bin_file_name;
++	if (dev->bin_file_name)
++		dev_info(dev->dev, "Using bin file %s\n", dev->bin_file_name);
++
++	of_node_put(np);
++
++	return dev->bin_file_name ? true : false;
++}
++EXPORT_SYMBOL_GPL(mt76_check_bin_file_mode);
++
+ void
+ mt76_eeprom_override(struct mt76_phy *phy)
+ {
+diff --git a/mt76.h b/mt76.h
+index 3341720c..7d6e3241 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -894,6 +894,8 @@ struct mt76_dev {
+ 		struct mt76_usb usb;
+ 		struct mt76_sdio sdio;
+ 	};
++
++	const char *bin_file_name;
+ };
+ 
+ struct mt76_power_limits {
+@@ -1030,6 +1032,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
+ int mt76_eeprom_init(struct mt76_dev *dev, int len);
+ void mt76_eeprom_override(struct mt76_phy *phy);
+ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
++bool mt76_check_bin_file_mode(struct mt76_dev *dev);
+ 
+ struct mt76_queue *
+ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 60e98463..85d9e057 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -61,8 +61,11 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
+ 	}
+ }
+ 
+-static char *mt7996_eeprom_name(struct mt7996_dev *dev)
++const char *mt7996_eeprom_name(struct mt7996_dev *dev)
+ {
++	if (dev->bin_file_mode)
++		return dev->mt76.bin_file_name;
++
+ 	/* reserve for future variants */
+ 	if (dev->testmode_enable)
+ 		return MT7996_EEPROM_DEFAULT_TM;
+@@ -112,7 +115,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
+ 		return ret;
+ 
+ 	if (!fw || !fw->data) {
+-		dev_err(dev->mt76.dev, "Invalid default bin\n");
++		if (dev->bin_file_mode)
++			dev_err(dev->mt76.dev, "Invalid bin (bin file mode)\n");
++		else
++			dev_err(dev->mt76.dev, "Invalid default bin\n");
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+@@ -126,18 +132,45 @@ out:
+ 	return ret;
+ }
+ 
++static int mt7996_eeprom_load_flash(struct mt7996_dev *dev)
++{
++	int ret = 1;
++
++	/* return > 0 for load success, return 0 for load failed, return < 0 for non memory */
++	dev->bin_file_mode = mt76_check_bin_file_mode(&dev->mt76);
++	if (dev->bin_file_mode) {
++		dev->mt76.eeprom.size = MT7996_EEPROM_SIZE;
++		dev->mt76.eeprom.data = devm_kzalloc(dev->mt76.dev, dev->mt76.eeprom.size,
++						     GFP_KERNEL);
++		if (!dev->mt76.eeprom.data)
++			return -ENOMEM;
++
++		if (mt7996_eeprom_load_default(dev))
++			return 0;
++
++		if (mt7996_check_eeprom(dev))
++			return 0;
++	} else {
++		ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
++	}
++
++	return ret;
++}
++
+ int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev)
+ {
+ 	u8 *eeprom;
+ 	int ret;
+ 
+ 	/* load eeprom in flash or bin file mode to determine fw mode */
+-	ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
++	ret = mt7996_eeprom_load_flash(dev);
++
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	if (ret) {
+ 		dev->flash_mode = true;
++		dev->eeprom_mode = dev->bin_file_mode ? BIN_FILE_MODE : FLASH_MODE;
+ 		eeprom = dev->mt76.eeprom.data;
+ 		/* testmode enable priority: eeprom field > module parameter */
+ 		dev->testmode_enable = !mt7996_check_eeprom(dev) ? eeprom[MT_EE_TESTMODE_EN] :
+@@ -171,6 +204,7 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
+ 			if (ret < 0)
+ 				return ret;
+ 		}
++		dev->eeprom_mode = EFUSE_MODE;
+ 	}
+ 
+ 	return mt7996_check_eeprom(dev);
+@@ -306,6 +340,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ 			return ret;
+ 
+ 		dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
++		dev->bin_file_mode = false;
++		dev->eeprom_mode = DEFAULT_BIN_MODE;
+ 		ret = mt7996_eeprom_load_default(dev);
+ 		if (ret)
+ 			return ret;
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 7ff290f4..20dd8771 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -99,6 +99,13 @@ enum mt7996_eeprom_band {
+ 	MT_EE_BAND_SEL_6GHZ,
+ };
+ 
++enum mt7915_eeprom_mode {
++	DEFAULT_BIN_MODE,
++	EFUSE_MODE,
++	FLASH_MODE,
++	BIN_FILE_MODE,
++};
++
+ static inline int
+ mt7996_get_channel_group_5g(int channel)
+ {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 9ab86eaf..6ef6bad9 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -380,6 +380,8 @@ struct mt7996_dev {
+ 	bool has_eht:1;
+ 
+ 	bool testmode_enable;
++	bool bin_file_mode;
++	u8 eeprom_mode;
+ 
+ 	bool ibf;
+ 	u8 fw_debug_wm;
+@@ -519,6 +521,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
+ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+ int mt7996_register_device(struct mt7996_dev *dev);
+ void mt7996_unregister_device(struct mt7996_dev *dev);
++const char *mt7996_eeprom_name(struct mt7996_dev *dev);
+ int mt7996_eeprom_init(struct mt7996_dev *dev);
+ int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev);
+ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 2aee3ab0..2ab2a8a8 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2525,6 +2525,44 @@ static const struct file_operations mt7996_txpower_sku_fops = {
+ 	.llseek = default_llseek,
+ };
+ 
++static int mt7996_show_eeprom_mode(struct seq_file *s, void *data)
++{
++	struct mt7996_dev *dev = dev_get_drvdata(s->private);
++	struct mt76_dev *mdev = &dev->mt76;
++#ifdef CONFIG_NL80211_TESTMODE
++	const char *mtd_name = mdev->test_mtd.name;
++	u32 mtd_offset = mdev->test_mtd.offset;
++#else
++	const char *mtd_name = NULL;
++	u32 mtd_offset;
++#endif
++
++	seq_printf(s, "Current eeprom mode:\n");
++
++	switch (dev->eeprom_mode) {
++	case DEFAULT_BIN_MODE:
++		seq_printf(s, "   default bin mode\n   filename = %s\n", mt7996_eeprom_name(dev));
++		break;
++	case EFUSE_MODE:
++		seq_printf(s, "   efuse mode\n");
++		break;
++	case FLASH_MODE:
++		if (mtd_name)
++			seq_printf(s, "   flash mode\n   mtd name = %s\n   flash offset = 0x%x\n",
++				   mtd_name, mtd_offset);
++		else
++			seq_printf(s, "   flash mode\n");
++		break;
++	case BIN_FILE_MODE:
++		seq_printf(s, "   bin file mode\n   filename = %s\n", mt7996_eeprom_name(dev));
++		break;
++	default:
++		break;
++	}
++
++	return 0;
++}
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -2570,6 +2608,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ 	debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level);
+ 	debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
+ 	debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "eeprom_mode", dir,
++				    mt7996_show_eeprom_mode);
+ 
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
+ 				    mt7996_wtbl_read);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
new file mode 100644
index 0000000..6b18fb0
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch
@@ -0,0 +1,310 @@
+From f3ff5d5029a0a589e797dd2536070d3a3e4e30a6 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 1 Mar 2023 12:12:51 +0800
+Subject: [PATCH 1008/1015] wifi: mt76: mt7996: add normal mode pre-calibration
+ support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76_connac_mcu.h |   1 +
+ mt7996/eeprom.c   |  23 +++++++
+ mt7996/eeprom.h   |   2 +
+ mt7996/init.c     |   6 ++
+ mt7996/main.c     |   6 ++
+ mt7996/mcu.c      | 166 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mt7996.h   |   2 +
+ 7 files changed, 206 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 262abf88..42246fb9 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1229,6 +1229,7 @@ enum {
+ 	MCU_UNI_CMD_VOW = 0x37,
+ 	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
+ 	MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
++	MCU_UNI_CMD_PRECAL_RESULT = 0x47,
+ 	MCU_UNI_CMD_RRO = 0x57,
+ 	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+ 	MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 85d9e057..bee4a4b5 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -330,6 +330,25 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
+ 	return mt7996_eeprom_parse_band_config(phy);
+ }
+ 
++static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
++{
++	struct mt76_dev *mdev = &dev->mt76;
++	u8 *eeprom = mdev->eeprom.data;
++	u32 offs = MT_EE_DO_PRE_CAL;
++	u32 size, val = eeprom[offs];
++
++	if (!dev->flash_mode || !val)
++		return 0;
++
++	size = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
++
++	dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++	if (!dev->cal)
++		return -ENOMEM;
++
++	return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, size);
++}
++
+ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ {
+ 	int ret;
+@@ -347,6 +366,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
+ 			return ret;
+ 	}
+ 
++	ret = mt7996_eeprom_load_precal(dev);
++	if (ret)
++		return ret;
++
+ 	ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);
+ 	if (ret < 0)
+ 		return ret;
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 20dd8771..0f3f31d8 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -25,6 +25,8 @@ enum mt7996_eeprom_field {
+ 	MT_EE_TX0_POWER_6G =	0x1310,
+ 
+ 	__MT_EE_MAX =	0x1dff,
++	/* 0x1e10 ~ 0x2d644 used to save group cal data */
++	MT_EE_PRECAL =		0x1e10,
+ };
+ 
+ #define MT_EE_WIFI_CONF0_TX_PATH		GENMASK(2, 0)
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 40d610ae..31695090 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -675,6 +675,12 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ 	if (ret < 0)
+ 		return ret;
+ 
++	if (dev->flash_mode) {
++		ret = mt7996_mcu_apply_group_cal(dev);
++		if (ret)
++			return ret;
++	}
++
+ 	/* Beacon and mgmt frames should occupy wcid 0 */
+ 	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
+ 	if (idx)
+diff --git a/mt7996/main.c b/mt7996/main.c
+index e5627c96..d40d3047 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -312,6 +312,12 @@ int mt7996_set_channel(struct mt7996_phy *phy)
+ 
+ 	mt76_set_channel(phy->mt76);
+ 
++	if (dev->flash_mode) {
++		ret = mt7996_mcu_apply_tx_dpd(phy);
++		if (ret)
++			goto out;
++	}
++
+ 	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
+ 	if (ret)
+ 		goto out;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 1fb7bae1..6add77da 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3386,6 +3386,172 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
+ 	return 0;
+ }
+ 
++static int mt7996_mcu_set_pre_cal(struct mt7996_dev *dev, u32 idx,
++				  u8 *cal, u32 len, u32 cal_id)
++{
++#define PRECAL_CMD_PRE_CAL_RESULT	0x0
++	struct {
++		/* fixed field */
++		u8 action;
++		u8 dest;
++		u8 attribute;
++		u8 tag_num;
++
++		__le16 tag;
++		__le16 len;
++
++		__le32 cal_id;
++		s8 precal;
++		u8 band;
++		u8 rsv[2];
++		__le32 idx;
++		__le32 cal_len;
++	} req = {
++		.tag = cpu_to_le16(PRECAL_CMD_PRE_CAL_RESULT),
++		.len = cpu_to_le16(sizeof(req) - 4 + len),
++		.cal_id = cpu_to_le32(cal_id),
++		.idx = cpu_to_le32(idx),
++		.cal_len = cpu_to_le32(len),
++	};
++	struct sk_buff *skb;
++
++	if (!len)
++		return 0;
++
++	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len);
++	if (!skb)
++		return -ENOMEM;
++
++	skb_put_data(skb, &req, sizeof(req));
++	skb_put_data(skb, cal, len);
++
++	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WM_UNI_CMD(PRECAL_RESULT), false);
++}
++
++int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev)
++{
++	u8 *cal = dev->cal, *eeprom = dev->mt76.eeprom.data;
++	u32 idx = 0, total_idx = MT_EE_CAL_GROUP_SIZE / MT_EE_CAL_UNIT;
++	u32 offs = MT_EE_DO_PRE_CAL;
++	int ret = 0;
++
++	if (!(eeprom[offs] & MT_EE_WIFI_CAL_GROUP))
++		return 0;
++
++	for (idx = 0; idx < total_idx; idx++, cal += MT_EE_CAL_UNIT) {
++		ret = mt7996_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT, RF_PRE_CAL);
++		if (ret)
++			goto out;
++	}
++
++	ret = mt7996_mcu_set_pre_cal(dev, total_idx, cal,
++				     MT_EE_CAL_GROUP_SIZE % MT_EE_CAL_UNIT, RF_PRE_CAL);
++
++out:
++	return ret;
++}
++
++int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy)
++{
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_phy *mphy = phy->mt76;
++	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
++	enum nl80211_band band = chandef->chan->band;
++	enum nl80211_chan_width bw = chandef->width;
++	const struct ieee80211_channel *chan_list;
++	u32 cal_id, chan_list_size, base_offset = 0, offs = MT_EE_DO_PRE_CAL;
++	u32 dpd_size_2g, dpd_size_5g, per_chan_size = DPD_PER_CH_BW20_SIZE;
++	u16 channel = ieee80211_frequency_to_channel(chandef->center_freq1);
++	u8 dpd_mask, *cal = dev->cal, *eeprom = dev->mt76.eeprom.data;
++	int idx, i, ret;
++
++	dpd_size_2g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_2GHZ);
++	dpd_size_5g = mt7996_get_dpd_per_band_size(dev, NL80211_BAND_5GHZ);
++
++	switch (band) {
++	case NL80211_BAND_2GHZ:
++		dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
++		/* channel 14 don't need DPD cal */
++		if (channel >= 1 && channel <= 4)
++			channel = 3;
++		else if (channel >= 5 && channel <= 9)
++			channel = 7;
++		else if (channel >= 10 && channel <= 13)
++			channel = 11;
++		else
++			return 0;
++		cal_id = RF_DPD_FLAT_CAL;
++		chan_list = dpd_2g_ch_list_bw20;
++		chan_list_size = dpd_2g_bw20_ch_num;
++		break;
++	case NL80211_BAND_5GHZ:
++		dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
++		cal_id = RF_DPD_FLAT_5G_CAL;
++		chan_list = mphy->sband_5g.sband.channels;
++		chan_list_size = mphy->sband_5g.sband.n_channels;
++		base_offset += dpd_size_2g;
++		if (bw == NL80211_CHAN_WIDTH_160) {
++			base_offset += mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
++			cal_id = RF_DPD_FLAT_5G_MEM_CAL;
++			chan_list = dpd_5g_ch_list_bw160;
++			chan_list_size = dpd_5g_bw160_ch_num;
++		} else if (bw > NL80211_CHAN_WIDTH_20) {
++			/* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
++			channel -= 2;
++		}
++		break;
++	case NL80211_BAND_6GHZ:
++		dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
++		cal_id = RF_DPD_FLAT_6G_CAL;
++		chan_list = mphy->sband_6g.sband.channels;
++		chan_list_size = mphy->sband_6g.sband.n_channels;
++		base_offset += dpd_size_2g + dpd_size_5g;
++		if (bw == NL80211_CHAN_WIDTH_160) {
++			base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE;
++			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
++			cal_id = RF_DPD_FLAT_6G_MEM_CAL;
++			chan_list = dpd_6g_ch_list_bw160;
++			chan_list_size = dpd_6g_bw160_ch_num;
++		} else if (bw == NL80211_CHAN_WIDTH_320) {
++			base_offset += mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE +
++				       dpd_6g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE;
++			per_chan_size = DPD_PER_CH_GT_BW20_SIZE;
++			cal_id = RF_DPD_FLAT_6G_MEM_CAL;
++			chan_list = dpd_6g_ch_list_bw320;
++			chan_list_size = dpd_6g_bw320_ch_num;
++		} else if (bw > NL80211_CHAN_WIDTH_20) {
++			/* apply (center channel - 2)'s dpd cal data for bw 40/80 channels */
++			channel -= 2;
++		}
++		break;
++	default:
++		dpd_mask = 0;
++		break;
++	}
++
++	if (!(eeprom[offs] & dpd_mask))
++		return 0;
++
++	for (idx = 0; idx < chan_list_size; idx++)
++		if (channel == chan_list[idx].hw_value)
++			break;
++	if (idx == chan_list_size)
++		return -EINVAL;
++
++	cal += MT_EE_CAL_GROUP_SIZE + base_offset + idx * per_chan_size;
++
++	for (i = 0; i < per_chan_size / MT_EE_CAL_UNIT; i++) {
++		ret = mt7996_mcu_set_pre_cal(dev, i, cal, MT_EE_CAL_UNIT, cal_id);
++		if (ret)
++			return ret;
++
++		cal += MT_EE_CAL_UNIT;
++	}
++
++	return ret;
++}
++
+ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
+ {
+ #define NIC_CAP	3
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 6ef6bad9..c16bc8b4 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -607,6 +607,8 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
+ int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
++int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev);
++int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
+ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+ #ifdef CONFIG_NL80211_TESTMODE
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
new file mode 100644
index 0000000..7ddc56f
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch
@@ -0,0 +1,220 @@
+From b99c942620576c63baffd687090febea5ab2973d Mon Sep 17 00:00:00 2001
+From: mtk23510 <rudra.shahi@mediatek.com>
+Date: Wed, 26 Apr 2023 20:08:10 +0800
+Subject: [PATCH 1009/1015] wifi: mt76: mt7996: Beacon protection feature added
+
+Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
+Change-Id: I0149a65f71d844fc395c2827a54f9360492d181e
+---
+ mt76_connac_mcu.h | 16 +++++++++
+ mt7996/main.c     |  4 +++
+ mt7996/mcu.c      | 86 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      | 11 ++++++
+ mt7996/mt7996.h   |  2 ++
+ 5 files changed, 119 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 42246fb9..a53fa138 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -415,6 +415,14 @@ struct sta_rec_he_6g_capa {
+ 	u8 rsv[2];
+ } __packed;
+ 
++struct sta_rec_pn_info {
++	__le16 tag;
++	__le16 len;
++	u8 pn[6];
++	u8 tsc_type;
++	u8 rsv;
++} __packed;
++
+ struct sec_key {
+ 	u8 cipher_id;
+ 	u8 cipher_len;
+@@ -767,6 +775,7 @@ struct wtbl_raw {
+ 					 sizeof(struct sta_rec_sec) +	\
+ 					 sizeof(struct sta_rec_ra_fixed) + \
+ 					 sizeof(struct sta_rec_he_6g_capa) + \
++					 sizeof(struct sta_rec_pn_info) + \
+ 					 sizeof(struct tlv) +		\
+ 					 MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
+ 
+@@ -796,6 +805,7 @@ enum {
+ 	STA_REC_HE_6G = 0x17,
+ 	STA_REC_HE_V2 = 0x19,
+ 	STA_REC_EHT = 0x22,
++	STA_REC_PN_INFO = 0x26,
+ 	STA_REC_HDRT = 0x28,
+ 	STA_REC_HDR_TRANS = 0x2B,
+ 	STA_REC_MAX_NUM
+@@ -1077,6 +1087,11 @@ enum mcu_cipher_type {
+ 	MCU_CIPHER_GCMP_256,
+ 	MCU_CIPHER_WAPI,
+ 	MCU_CIPHER_BIP_CMAC_128,
++	MCU_CIPHER_BIP_CMAC_256,
++	MCU_CIPHER_BCN_PROT_CMAC_128,
++	MCU_CIPHER_BCN_PROT_CMAC_256,
++	MCU_CIPHER_BCN_PROT_GMAC_128,
++	MCU_CIPHER_BCN_PROT_GMAC_256,
+ };
+ 
+ enum {
+@@ -1295,6 +1310,7 @@ enum {
+ 	UNI_BSS_INFO_RATE = 11,
+ 	UNI_BSS_INFO_QBSS = 15,
+ 	UNI_BSS_INFO_SEC = 16,
++	UNI_BSS_INFO_BCN_PROT = 17,
+ 	UNI_BSS_INFO_TXCMD = 18,
+ 	UNI_BSS_INFO_UAPSD = 19,
+ 	UNI_BSS_INFO_PS = 21,
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d40d3047..d3d10fab 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -400,6 +400,10 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 	}
+ 
+ 	mt76_wcid_key_setup(&dev->mt76, wcid, key);
++
++	if (key->keyidx == 6 || key->keyidx == 7)
++		mt7996_mcu_bcn_prot_enable(dev, vif, key);
++
+ 	err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
+ 				 key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
+ 				 &msta->wcid, cmd);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6add77da..53d2fc73 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2133,6 +2133,92 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ 	return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
+ }
+ 
++static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++			    u8 *pn)
++{
++#define TSC_TYPE_BIGTK_PN 2
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct sta_rec_pn_info *pn_info;
++	struct sk_buff *skb, *rskb;
++	struct tlv *tlv;
++	int ret;
++
++	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
++	pn_info = (struct sta_rec_pn_info *)tlv;
++
++	pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
++	ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
++				MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE), true, &rskb);
++	if (ret)
++		return ret;
++
++	skb_pull(rskb, 4);
++
++	pn_info = (struct sta_rec_pn_info *)rskb->data;
++	if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
++		memcpy(pn, pn_info->pn, 6);
++
++	dev_kfree_skb(rskb);
++	return 0;
++}
++
++int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++		       struct ieee80211_key_conf *key)
++{
++#define WPA_BIGTK_MAX_LEN 32
++	int len = sizeof(struct bss_req_hdr) + sizeof(struct mt7996_mcu_bcn_prot_tlv);
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	int ret;
++	struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
++	struct sk_buff *skb;
++	struct tlv *tlv;
++	u8 pn[6] = {0};
++
++	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT,
++				sizeof(*bcn_prot));
++
++	bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
++
++	ret = mt7996_mcu_get_pn(dev, vif, pn);
++	if (ret) {
++		dev_kfree_skb(skb);
++		return ret;
++	}
++
++	switch(key->cipher){
++	case WLAN_CIPHER_SUITE_AES_CMAC:
++		bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
++		break;
++	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
++		bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
++		break;
++	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
++		bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
++		break;
++	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
++	default:
++		dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
++		dev_kfree_skb(skb);
++		return -EOPNOTSUPP;
++	}
++
++	pn[0]++;
++	memcpy(bcn_prot->pn, pn, 6);
++	bcn_prot->enable = 1;
++	memcpy(bcn_prot->key, key->key, WPA_BIGTK_MAX_LEN);
++	bcn_prot->key_id = key->keyidx;
++
++	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
++				   MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
++}
+ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
+ 			    struct ieee80211_vif *vif, bool enable)
+ {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index baffbcd7..f32ac153 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -262,6 +262,17 @@ struct bss_rate_tlv {
+ 	u8 __rsv2[9];
+ } __packed;
+ 
++struct mt7996_mcu_bcn_prot_tlv {
++	__le16 tag;
++	__le16 len;
++	u8 pn[6];
++	u8 enable;
++	u8 cipher_id;
++	u8 key[32];
++	u8 key_id;
++	u8 __rsv[3];
++} __packed;
++
+ struct bss_ra_tlv {
+ 	__le16 tag;
+ 	__le16 len;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index c16bc8b4..94b62211 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -710,6 +710,8 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ 		       struct mt76_connac_sta_key_conf *sta_key_conf,
+ 		       struct ieee80211_key_conf *key, int mcu_cmd,
+ 		       struct mt76_wcid *wcid, enum set_key_cmd cmd);
++int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
++		       struct ieee80211_key_conf *key);
+ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ 				     struct ieee80211_vif *vif,
+ 				     struct ieee80211_sta *sta);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
new file mode 100644
index 0000000..999d9ba
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch
@@ -0,0 +1,490 @@
+From 639385416a573ae5ce631a0323c5541dea3e406c Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 22 Mar 2023 11:19:52 +0800
+Subject: [PATCH 1010/1015] wifi: mt76: testmode: add testmode ZWDFS
+ verification support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt76.h            |   8 ++
+ mt7996/mt7996.h   |   1 +
+ mt7996/testmode.c | 248 ++++++++++++++++++++++++++++++++++++++++++++--
+ mt7996/testmode.h |  44 ++++++++
+ testmode.c        |  22 +++-
+ tools/fields.c    |  15 +++
+ 6 files changed, 326 insertions(+), 12 deletions(-)
+
+diff --git a/mt76.h b/mt76.h
+index 7d6e3241..5b442691 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -732,6 +732,14 @@ struct mt76_testmode_data {
+ 	} cfg;
+ 
+ 	u8 aid;
++
++	u8 offchan_ch;
++	u8 offchan_center_ch;
++	u8 offchan_bw;
++
++	u8 ipi_threshold;
++	u32 ipi_period;
++	u8 ipi_reset;
+ };
+ 
+ struct mt76_vif {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 94b62211..abdbb1ef 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -295,6 +295,7 @@ struct mt7996_phy {
+ 
+ 	struct mib_stats mib;
+ 	struct mt76_channel_state state_ts;
++	struct delayed_work ipi_work;
+ 
+ 	bool has_aux_rx;
+ 
+diff --git a/mt7996/testmode.c b/mt7996/testmode.c
+index 7d36902e..ba3cd802 100644
+--- a/mt7996/testmode.c
++++ b/mt7996/testmode.c
+@@ -16,6 +16,12 @@ enum {
+ 	TM_CHANGED_TX_LENGTH,
+ 	TM_CHANGED_TX_TIME,
+ 	TM_CHANGED_CFG,
++	TM_CHANGED_OFF_CHAN_CH,
++	TM_CHANGED_OFF_CHAN_CENTER_CH,
++	TM_CHANGED_OFF_CHAN_BW,
++	TM_CHANGED_IPI_THRESHOLD,
++	TM_CHANGED_IPI_PERIOD,
++	TM_CHANGED_IPI_RESET,
+ 
+ 	/* must be last */
+ 	NUM_TM_CHANGED
+@@ -27,20 +33,31 @@ static const u8 tm_change_map[] = {
+ 	[TM_CHANGED_TX_LENGTH] = MT76_TM_ATTR_TX_LENGTH,
+ 	[TM_CHANGED_TX_TIME] = MT76_TM_ATTR_TX_TIME,
+ 	[TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
++	[TM_CHANGED_OFF_CHAN_CH] = MT76_TM_ATTR_OFF_CH_SCAN_CH,
++	[TM_CHANGED_OFF_CHAN_CENTER_CH] = MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH,
++	[TM_CHANGED_OFF_CHAN_BW] = MT76_TM_ATTR_OFF_CH_SCAN_BW,
++	[TM_CHANGED_IPI_THRESHOLD] = MT76_TM_ATTR_IPI_THRESHOLD,
++	[TM_CHANGED_IPI_PERIOD] = MT76_TM_ATTR_IPI_PERIOD,
++	[TM_CHANGED_IPI_RESET] = MT76_TM_ATTR_IPI_RESET,
+ };
+ 
+-static u8 mt7996_tm_bw_mapping(enum nl80211_chan_width width, enum bw_mapping_method method)
++static void mt7996_tm_ipi_work(struct work_struct *work);
++
++static u32 mt7996_tm_bw_mapping(enum nl80211_chan_width width, enum bw_mapping_method method)
+ {
+-	static const u8 width_to_bw[][NUM_BW_MAP] = {
+-		[NL80211_CHAN_WIDTH_40] = {FW_CDBW_40MHZ, TM_CBW_40MHZ},
+-		[NL80211_CHAN_WIDTH_80] = {FW_CDBW_80MHZ, TM_CBW_80MHZ},
+-		[NL80211_CHAN_WIDTH_80P80] = {FW_CDBW_8080MHZ, TM_CBW_8080MHZ},
+-		[NL80211_CHAN_WIDTH_160] = {FW_CDBW_160MHZ, TM_CBW_160MHZ},
+-		[NL80211_CHAN_WIDTH_5] = {FW_CDBW_5MHZ, TM_CBW_5MHZ},
+-		[NL80211_CHAN_WIDTH_10] = {FW_CDBW_10MHZ, TM_CBW_10MHZ},
+-		[NL80211_CHAN_WIDTH_20] = {FW_CDBW_20MHZ, TM_CBW_20MHZ},
+-		[NL80211_CHAN_WIDTH_20_NOHT] = {FW_CDBW_20MHZ, TM_CBW_20MHZ},
+-		[NL80211_CHAN_WIDTH_320] = {FW_CDBW_320MHZ, TM_CBW_320MHZ},
++	static const u32 width_to_bw[][NUM_BW_MAP] = {
++		[NL80211_CHAN_WIDTH_40] = {FW_CDBW_40MHZ, TM_CBW_40MHZ, 40,
++					   FIRST_CONTROL_CHAN_BITMAP_BW40},
++		[NL80211_CHAN_WIDTH_80] = {FW_CDBW_80MHZ, TM_CBW_80MHZ, 80,
++					   FIRST_CONTROL_CHAN_BITMAP_BW80},
++		[NL80211_CHAN_WIDTH_80P80] = {FW_CDBW_8080MHZ, TM_CBW_8080MHZ, 80, 0x0},
++		[NL80211_CHAN_WIDTH_160] = {FW_CDBW_160MHZ, TM_CBW_160MHZ, 160,
++					    FIRST_CONTROL_CHAN_BITMAP_BW160},
++		[NL80211_CHAN_WIDTH_5] = {FW_CDBW_5MHZ, TM_CBW_5MHZ, 5, 0x0},
++		[NL80211_CHAN_WIDTH_10] = {FW_CDBW_10MHZ, TM_CBW_10MHZ, 10, 0x0},
++		[NL80211_CHAN_WIDTH_20] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, 20, 0x0},
++		[NL80211_CHAN_WIDTH_20_NOHT] = {FW_CDBW_20MHZ, TM_CBW_20MHZ, 20, 0x0},
++		[NL80211_CHAN_WIDTH_320] = {FW_CDBW_320MHZ, TM_CBW_320MHZ, 320, 0x0},
+ 	};
+ 
+ 	if (width >= ARRAY_SIZE(width_to_bw))
+@@ -217,6 +234,9 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en)
+ 
+ 	/* use firmware counter for RX stats */
+ 	phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
++
++	if (en)
++		INIT_DELAYED_WORK(&phy->ipi_work, mt7996_tm_ipi_work);
+ }
+ 
+ static void
+@@ -829,6 +849,204 @@ void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	}
+ }
+ 
++static u8
++mt7996_tm_get_center_chan(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef)
++{
++	struct mt76_phy *mphy = phy->mt76;
++	const struct ieee80211_channel *chan = mphy->sband_5g.sband.channels;
++	u32 bitmap, i, offset, width_mhz, size = mphy->sband_5g.sband.n_channels;
++	u16 first_control = 0, control_chan = chandef->chan->hw_value;
++
++	bitmap = mt7996_tm_bw_mapping(chandef->width, BW_MAP_NL_TO_CONTROL_BITMAP_5G);
++	if (!bitmap)
++		return control_chan;
++
++	width_mhz = mt7996_tm_bw_mapping(chandef->width, BW_MAP_NL_TO_MHZ);
++	offset = width_mhz / 10 - 2;
++
++	for (i = 0; i < size; i++) {
++		if (!((1 << i) & bitmap))
++			continue;
++
++		if (control_chan >= chan[i].hw_value)
++			first_control = chan[i].hw_value;
++		else
++			break;
++	}
++
++	if (i == size || first_control == 0)
++		return control_chan;
++
++	return first_control + offset;
++}
++
++static int
++mt7996_tm_set_offchan(struct mt7996_phy *phy, bool no_center)
++{
++	struct mt76_phy *mphy = phy->mt76;
++	struct mt7996_dev *dev = phy->dev;
++	struct ieee80211_hw *hw = mphy->hw;
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct cfg80211_chan_def chandef = {};
++	struct ieee80211_channel *chan;
++	int ret, freq = ieee80211_channel_to_frequency(td->offchan_ch, NL80211_BAND_5GHZ);
++
++	if (!mphy->cap.has_5ghz || !freq) {
++		ret = -EINVAL;
++		dev_info(dev->mt76.dev, "Failed to set offchan (invalid band or channel)!\n");
++		goto out;
++	}
++
++	chandef.width = td->offchan_bw;
++	chan = ieee80211_get_channel(hw->wiphy, freq);
++	chandef.chan = chan;
++	if (no_center)
++		td->offchan_center_ch = mt7996_tm_get_center_chan(phy, &chandef);
++	chandef.center_freq1 = ieee80211_channel_to_frequency(td->offchan_center_ch,
++							      NL80211_BAND_5GHZ);
++	if (!cfg80211_chandef_valid(&chandef)) {
++		ret = -EINVAL;
++		dev_info(dev->mt76.dev, "Failed to set offchan, chandef is invalid!\n");
++		goto out;
++	}
++
++	memset(&dev->rdd2_chandef, 0, sizeof(struct cfg80211_chan_def));
++
++	ret = mt7996_mcu_rdd_background_enable(phy, &chandef);
++
++	if (ret)
++		goto out;
++
++	dev->rdd2_phy = phy;
++	dev->rdd2_chandef = chandef;
++
++	return 0;
++
++out:
++	td->offchan_ch = 0;
++	td->offchan_center_ch = 0;
++	td->offchan_bw = 0;
++
++	return ret;
++}
++
++static void
++mt7996_tm_ipi_hist_ctrl(struct mt7996_phy *phy, struct mt7996_tm_rdd_ipi_ctrl *data, u8 cmd)
++{
++#define MT_IPI_RESET		0x830a5dfc
++#define MT_IPI_RESET_MASK	BIT(28)
++#define MT_IPI_COUNTER_BASE	0x83041000
++#define MT_IPI_COUNTER(idx)	(MT_IPI_COUNTER_BASE + ((idx) * 4))
++	struct mt7996_dev *dev = phy->dev;
++	bool val;
++	int i;
++
++	if (cmd == RDD_SET_IPI_HIST_RESET) {
++		val = mt76_rr(dev, MT_IPI_RESET) & MT_IPI_RESET_MASK;
++		mt76_rmw_field(dev, MT_IPI_RESET, MT_IPI_RESET_MASK, !val);
++		return;
++	}
++
++	for (i = 0; i < POWER_INDICATE_HIST_MAX; i++)
++		data->ipi_hist_val[i] = mt76_rr(dev, MT_IPI_COUNTER(i));
++}
++
++static void
++mt7996_tm_ipi_work(struct work_struct *work)
++{
++#define PRECISION	100
++	struct mt7996_phy *phy = container_of(work, struct mt7996_phy, ipi_work.work);
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct mt7996_tm_rdd_ipi_ctrl data;
++	u32 ipi_idx, ipi_free_count, ipi_percentage;
++	u32 ipi_hist_count_th = 0, ipi_hist_total_count = 0;
++	u32 self_idle_ratio, ipi_idle_ratio, channel_load;
++	u32 *ipi_hist_data;
++	const char *power_lower_bound, *power_upper_bound;
++	static const char * const ipi_idx_to_power_bound[] = {
++		[RDD_IPI_HIST_0] = "-92",
++		[RDD_IPI_HIST_1] = "-89",
++		[RDD_IPI_HIST_2] = "-86",
++		[RDD_IPI_HIST_3] = "-83",
++		[RDD_IPI_HIST_4] = "-80",
++		[RDD_IPI_HIST_5] = "-75",
++		[RDD_IPI_HIST_6] = "-70",
++		[RDD_IPI_HIST_7] = "-65",
++		[RDD_IPI_HIST_8] = "-60",
++		[RDD_IPI_HIST_9] = "-55",
++		[RDD_IPI_HIST_10] = "inf",
++	};
++
++	memset(&data, 0, sizeof(data));
++	mt7996_tm_ipi_hist_ctrl(phy, &data, RDD_IPI_HIST_ALL_CNT);
++
++	ipi_hist_data = data.ipi_hist_val;
++	for (ipi_idx = 0; ipi_idx < POWER_INDICATE_HIST_MAX; ipi_idx++) {
++		power_lower_bound = ipi_idx ? ipi_idx_to_power_bound[ipi_idx - 1] : "-inf";
++		power_upper_bound = ipi_idx_to_power_bound[ipi_idx];
++
++		dev_info(dev->mt76.dev, "IPI %d (power range: (%s, %s] dBm): ipi count = %d\n",
++			 ipi_idx, power_lower_bound, power_upper_bound, ipi_hist_data[ipi_idx]);
++
++		if (td->ipi_threshold <= ipi_idx && ipi_idx <= RDD_IPI_HIST_10)
++			ipi_hist_count_th += ipi_hist_data[ipi_idx];
++
++		ipi_hist_total_count += ipi_hist_data[ipi_idx];
++	}
++
++	ipi_free_count = ipi_hist_data[RDD_IPI_FREE_RUN_CNT];
++
++	dev_info(dev->mt76.dev, "IPI threshold %d: ipi_hist_count_th = %d, ipi_free_count = %d\n",
++		 td->ipi_threshold, ipi_hist_count_th, ipi_free_count);
++	dev_info(dev->mt76.dev, "TX assert time =  %d [ms]\n", data.tx_assert_time / 1000);
++
++	/* calculate channel load = (self idle ratio - idle ratio) / self idle ratio */
++	if (ipi_hist_count_th >= UINT_MAX / (100 * PRECISION))
++		ipi_percentage = 100 * PRECISION *
++				 (ipi_hist_count_th / (100 * PRECISION)) /
++				 (ipi_free_count / (100 * PRECISION));
++	else
++		ipi_percentage = PRECISION * 100 * ipi_hist_count_th / ipi_free_count;
++
++	ipi_idle_ratio = ((100 * PRECISION) - ipi_percentage) / PRECISION;
++
++	self_idle_ratio = PRECISION * 100 *
++			  (td->ipi_period - (data.tx_assert_time / 1000)) /
++			  td->ipi_period / PRECISION;
++
++	if (self_idle_ratio < ipi_idle_ratio)
++		channel_load = 0;
++	else
++		channel_load = self_idle_ratio - ipi_idle_ratio;
++
++	if (self_idle_ratio <= td->ipi_threshold) {
++		dev_info(dev->mt76.dev, "band[%d]: self idle ratio = %d%%, idle ratio = %d%%\n",
++			 phy->mt76->band_idx, self_idle_ratio, ipi_idle_ratio);
++		return;
++	}
++
++	channel_load = (100 * channel_load) / self_idle_ratio;
++	dev_info(dev->mt76.dev,
++		 "band[%d]: chan load = %d%%, self idle ratio = %d%%, idle ratio = %d%%\n",
++		 phy->mt76->band_idx, channel_load, self_idle_ratio, ipi_idle_ratio);
++}
++
++static int
++mt7996_tm_set_ipi(struct mt7996_phy *phy)
++{
++	struct mt76_testmode_data *td = &phy->mt76->test;
++
++	/* reset IPI CR */
++	mt7996_tm_ipi_hist_ctrl(phy, NULL, RDD_SET_IPI_HIST_RESET);
++
++	cancel_delayed_work(&phy->ipi_work);
++	ieee80211_queue_delayed_work(phy->mt76->hw, &phy->ipi_work,
++				     msecs_to_jiffies(td->ipi_period));
++
++	return 0;
++}
++
+ static void
+ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+ {
+@@ -853,6 +1071,14 @@ mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
+ 
+ 		mt7996_tm_set(dev, func_idx, td->cfg.type);
+ 	}
++	if ((changed & BIT(TM_CHANGED_OFF_CHAN_CH)) &&
++	    (changed & BIT(TM_CHANGED_OFF_CHAN_BW)))
++		mt7996_tm_set_offchan(phy, !(changed & BIT(TM_CHANGED_OFF_CHAN_CENTER_CH)));
++	if ((changed & BIT(TM_CHANGED_IPI_THRESHOLD)) &&
++	    (changed & BIT(TM_CHANGED_IPI_PERIOD)))
++		mt7996_tm_set_ipi(phy);
++	if (changed & BIT(TM_CHANGED_IPI_RESET))
++		mt7996_tm_ipi_hist_ctrl(phy, NULL, RDD_SET_IPI_HIST_RESET);
+ }
+ 
+ static int
+diff --git a/mt7996/testmode.h b/mt7996/testmode.h
+index 778c9bc6..09f81d39 100644
+--- a/mt7996/testmode.h
++++ b/mt7996/testmode.h
+@@ -27,9 +27,15 @@ enum {
+ 	FW_CDBW_8080MHZ,
+ };
+ 
++#define FIRST_CONTROL_CHAN_BITMAP_BW40		0x5555555
++#define FIRST_CONTROL_CHAN_BITMAP_BW80		0x111111
++#define FIRST_CONTROL_CHAN_BITMAP_BW160		0x100101
++
+ enum bw_mapping_method {
+ 	BW_MAP_NL_TO_FW,
+ 	BW_MAP_NL_TO_TM,
++	BW_MAP_NL_TO_MHZ,
++	BW_MAP_NL_TO_CONTROL_BITMAP_5G,
+ 
+ 	NUM_BW_MAP,
+ };
+@@ -308,4 +314,42 @@ struct mt7996_tm_rx_event {
+ 	};
+ } __packed;
+ 
++enum {
++	RDD_SET_IPI_CR_INIT,		/* CR initialization */
++	RDD_SET_IPI_HIST_RESET,		/* Reset IPI histogram counter */
++	RDD_SET_IDLE_POWER,		/* Idle power info */
++	RDD_SET_IPI_HIST_NUM
++};
++
++enum {
++	RDD_IPI_HIST_0,			/* IPI count for power <= -92 (dBm) */
++	RDD_IPI_HIST_1,			/* IPI count for -92 < power <= -89 (dBm) */
++	RDD_IPI_HIST_2,			/* IPI count for -89 < power <= -86 (dBm) */
++	RDD_IPI_HIST_3,			/* IPI count for -86 < power <= -83 (dBm) */
++	RDD_IPI_HIST_4,			/* IPI count for -83 < power <= -80 (dBm) */
++	RDD_IPI_HIST_5,			/* IPI count for -80 < power <= -75 (dBm) */
++	RDD_IPI_HIST_6,			/* IPI count for -75 < power <= -70 (dBm) */
++	RDD_IPI_HIST_7,			/* IPI count for -70 < power <= -65 (dBm) */
++	RDD_IPI_HIST_8,			/* IPI count for -65 < power <= -60 (dBm) */
++	RDD_IPI_HIST_9,			/* IPI count for -60 < power <= -55 (dBm) */
++	RDD_IPI_HIST_10,		/* IPI count for -55 < power        (dBm) */
++	RDD_IPI_FREE_RUN_CNT,		/* IPI count for counter++ per 8 us */
++	RDD_IPI_HIST_ALL_CNT,		/* Get all IPI */
++	RDD_IPI_HIST_0_TO_10_CNT,	/* Get IPI histogram 0 to 10 */
++	RDD_IPI_HIST_2_TO_10_CNT,	/* Get IPI histogram 2 to 10 */
++	RDD_TX_ASSERT_TIME,		/* Get band 1 TX assert time */
++	RDD_IPI_HIST_NUM
++};
++
++#define POWER_INDICATE_HIST_MAX		RDD_IPI_FREE_RUN_CNT
++#define IPI_HIST_TYPE_NUM		(POWER_INDICATE_HIST_MAX + 1)
++
++struct mt7996_tm_rdd_ipi_ctrl {
++	u8 ipi_hist_idx;
++	u8 band_idx;
++	u8 rsv[2];
++	__le32 ipi_hist_val[IPI_HIST_TYPE_NUM];
++	__le32 tx_assert_time;		/* unit: us */
++} __packed;
++
+ #endif
+diff --git a/testmode.c b/testmode.c
+index 74bb26fa..22d6afd4 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -25,6 +25,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+ 	[MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_DRV_DATA] = { .type = NLA_NESTED },
++	[MT76_TM_ATTR_OFF_CH_SCAN_CH] = { .type = NLA_U8 },
++	[MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH] = { .type = NLA_U8 },
++	[MT76_TM_ATTR_OFF_CH_SCAN_BW] = { .type = NLA_U8 },
++	[MT76_TM_ATTR_OFF_CH_SCAN_PATH] = { .type = NLA_U8 },
++	[MT76_TM_ATTR_IPI_THRESHOLD] = { .type = NLA_U8 },
++	[MT76_TM_ATTR_IPI_PERIOD] = { .type = NLA_U32 },
++	[MT76_TM_ATTR_IPI_RESET] = { .type = NLA_U8 },
+ };
+ EXPORT_SYMBOL_GPL(mt76_tm_policy);
+ 
+@@ -451,6 +458,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 	if (tb[MT76_TM_ATTR_TX_RATE_IDX])
+ 		td->tx_rate_idx = nla_get_u8(tb[MT76_TM_ATTR_TX_RATE_IDX]);
+ 
++	if (tb[MT76_TM_ATTR_IPI_PERIOD])
++		td->ipi_period = nla_get_u32(tb[MT76_TM_ATTR_IPI_PERIOD]);
++
+ 	if (mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_MODE], &td->tx_rate_mode,
+ 			   0, MT76_TM_TX_MODE_MAX) ||
+ 	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_NSS], &td->tx_rate_nss,
+@@ -466,7 +476,14 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 			   &td->tx_duty_cycle, 0, 99) ||
+ 	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
+ 			   &td->tx_power_control, 0, 1) ||
+-	    mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16))
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16) ||
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CH], &td->offchan_ch, 36, 196) ||
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH], &td->offchan_center_ch,
++			   36, 196) ||
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_BW],
++			   &td->offchan_bw, NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_160) ||
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_THRESHOLD], &td->ipi_threshold, 0, 10) ||
++	    mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_RESET], &td->ipi_reset, 0, 1))
+ 		goto out;
+ 
+ 	if (tb[MT76_TM_ATTR_TX_LENGTH]) {
+@@ -671,6 +688,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
+ 	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
+ 	    nla_put_u8(msg, MT76_TM_ATTR_AID, td->aid) ||
++	    nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CH, td->offchan_ch) ||
++	    nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH, td->offchan_center_ch) ||
++	    nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_BW, td->offchan_bw) ||
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
+ 	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
+diff --git a/tools/fields.c b/tools/fields.c
+index b22b3fc8..55854a6f 100644
+--- a/tools/fields.c
++++ b/tools/fields.c
+@@ -35,6 +35,15 @@ static const char * const testmode_tx_mode[] = {
+ 	[MT76_TM_TX_MODE_EHT_MU] = "eht_mu",
+ };
+ 
++static const char * const testmode_offchan_bw[] = {
++	[NL80211_CHAN_WIDTH_20_NOHT] = "NOHT",
++	[NL80211_CHAN_WIDTH_20] = "20",
++	[NL80211_CHAN_WIDTH_40] = "40",
++	[NL80211_CHAN_WIDTH_80] = "80",
++	[NL80211_CHAN_WIDTH_80P80] = "80p80",
++	[NL80211_CHAN_WIDTH_160] = "160",
++};
++
+ static void print_enum(const struct tm_field *field, struct nlattr *attr)
+ {
+ 	unsigned int i = nla_get_u8(attr);
+@@ -387,6 +396,12 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+ 	FIELD(u8, AID, "aid"),
+ 	FIELD(u8, RU_ALLOC, "ru_alloc"),
+ 	FIELD(u8, RU_IDX, "ru_idx"),
++	FIELD(u8, OFF_CH_SCAN_CH, "offchan_ch"),
++	FIELD(u8, OFF_CH_SCAN_CENTER_CH, "offchan_center_ch"),
++	FIELD_ENUM(OFF_CH_SCAN_BW, "offchan_bw", testmode_offchan_bw),
++	FIELD(u8, IPI_THRESHOLD, "ipi_threshold"),
++	FIELD(u32, IPI_PERIOD, "ipi_period"),
++	FIELD(u8, IPI_RESET, "ipi_reset"),
+ 	FIELD_MAC(MAC_ADDRS, "mac_addrs"),
+ 	FIELD_NESTED_RO(STATS, stats, "",
+ 			.print_extra = print_extra_stats),
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch
new file mode 100644
index 0000000..0fcae6a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1011-wifi-mt76-mt7996-add-single-sku.patch
@@ -0,0 +1,337 @@
+From 0d9ff0aa7afe37146c6015e416d9b944b4bb16f5 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
+Date: Tue, 18 Apr 2023 15:56:22 +0800
+Subject: [PATCH 1011/1015] wifi: mt76: mt7996: add single sku
+
+Add single sku and default enable sku.
+
+Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+---
+ eeprom.c          | 38 ++++++++++++++++++--
+ mt76.h            | 10 ++++++
+ mt76_connac_mcu.c |  2 +-
+ mt7996/init.c     |  2 ++
+ mt7996/main.c     | 15 ++++++++
+ mt7996/mcu.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      | 12 +++++++
+ mt7996/mt7996.h   |  2 ++
+ 8 files changed, 169 insertions(+), 4 deletions(-)
+
+diff --git a/eeprom.c b/eeprom.c
+index 412740f0..3abefb5a 100644
+--- a/eeprom.c
++++ b/eeprom.c
+@@ -301,6 +301,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
+ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ 			      struct ieee80211_channel *chan,
+ 			      struct mt76_power_limits *dest,
++			      struct mt76_power_path_limits *dest_path,
+ 			      s8 target_power)
+ {
+ 	struct mt76_dev *dev = phy->dev;
+@@ -308,16 +309,17 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ 	const __be32 *val;
+ 	char name[16];
+ 	u32 mcs_rates = dev->drv->mcs_rates;
+-	u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
+ 	char band;
+ 	size_t len;
+ 	s8 max_power = 0;
+ 	s8 txs_delta;
+ 
+ 	if (!mcs_rates)
+-		mcs_rates = 10;
++		mcs_rates = 12;
+ 
+ 	memset(dest, target_power, sizeof(*dest));
++	if (dest_path != NULL)
++		memset(dest_path, 0, sizeof(*dest_path));
+ 
+ 	if (!IS_ENABLED(CONFIG_OF))
+ 		return target_power;
+@@ -365,11 +367,41 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ 				     ARRAY_SIZE(dest->mcs), val, len,
+ 				     target_power, txs_delta, &max_power);
+ 
+-	val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
++	val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
+ 	mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+ 				     ARRAY_SIZE(dest->ru), val, len,
+ 				     target_power, txs_delta, &max_power);
+ 
++	val = mt76_get_of_array(np, "rates-eht-ru", &len, ARRAY_SIZE(dest->eht_ru[0]) + 1);
++	mt76_apply_multi_array_limit(dest->eht_ru[0], ARRAY_SIZE(dest->eht_ru[0]),
++				     ARRAY_SIZE(dest->eht_ru), val, len,
++				     target_power, txs_delta, &max_power);
++
++	if (dest_path == NULL)
++		return max_power;
++
++	val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest_path->cck));
++	mt76_apply_array_limit(dest_path->cck, ARRAY_SIZE(dest_path->cck), val,
++			       target_power, txs_delta, &max_power);
++
++	val = mt76_get_of_array(np, "paths-ofdm", &len, ARRAY_SIZE(dest_path->ofdm));
++	mt76_apply_array_limit(dest_path->ofdm, ARRAY_SIZE(dest_path->ofdm), val,
++			       target_power, txs_delta, &max_power);
++
++	val = mt76_get_of_array(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest_path->ofdm_bf));
++	mt76_apply_array_limit(dest_path->ofdm_bf, ARRAY_SIZE(dest_path->ofdm_bf), val,
++			       target_power, txs_delta, &max_power);
++
++	val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest_path->ru[0]) + 1);
++	mt76_apply_multi_array_limit(dest_path->ru[0], ARRAY_SIZE(dest_path->ru[0]),
++				     ARRAY_SIZE(dest_path->ru), val, len,
++				     target_power, txs_delta, &max_power);
++
++	val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest_path->ru_bf[0]) + 1);
++	mt76_apply_multi_array_limit(dest_path->ru_bf[0], ARRAY_SIZE(dest_path->ru_bf[0]),
++				     ARRAY_SIZE(dest_path->ru_bf), val, len,
++				     target_power, txs_delta, &max_power);
++
+ 	return max_power;
+ }
+ EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
+diff --git a/mt76.h b/mt76.h
+index 5b442691..8abb6f41 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -911,6 +911,15 @@ struct mt76_power_limits {
+ 	s8 ofdm[8];
+ 	s8 mcs[4][10];
+ 	s8 ru[7][12];
++	s8 eht_ru[16][16];
++};
++
++struct mt76_power_path_limits {
++	s8 cck[5];
++	s8 ofdm[5];
++	s8 ofdm_bf[4];
++	s8 ru[16][15];
++	s8 ru_bf[16][15];
+ };
+ 
+ struct mt76_ethtool_worker_info {
+@@ -1493,6 +1502,7 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);
+ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ 			      struct ieee80211_channel *chan,
+ 			      struct mt76_power_limits *dest,
++			      struct mt76_power_path_limits *dest_path,
+ 			      s8 target_power);
+ 
+ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index c24dac10..ca7b6a6f 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -2235,7 +2235,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
+ 			sar_power = mt76_get_sar_power(phy, &chan, reg_power);
+ 
+ 			mt76_get_rate_power_limits(phy, &chan, &limits,
+-						   sar_power);
++						   NULL, sar_power);
+ 
+ 			tx_power_tlv.last_msg = ch_list[idx] == last_ch;
+ 			sku_tlbv.channel = ch_list[idx];
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 31695090..a6caf4f1 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -294,6 +294,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+ 	int nss_delta = mt76_tx_power_nss_delta(nss);
+ 	int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
+ 	struct mt76_power_limits limits;
++	struct mt76_power_path_limits limits_path;
+ 
+ 	for (i = 0; i < sband->n_channels; i++) {
+ 		struct ieee80211_channel *chan = &sband->channels[i];
+@@ -302,6 +303,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+ 		target_power += pwr_delta;
+ 		target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
+ 							  &limits,
++							  &limits_path,
+ 							  target_power);
+ 		target_power += nss_delta;
+ 		target_power = DIV_ROUND_UP(target_power, 2);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d3d10fab..71c346cb 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -77,6 +77,15 @@ int mt7996_run(struct ieee80211_hw *hw)
+ 	if (ret)
+ 		goto out;
+ 
++#ifdef CONFIG_MTK_DEBUG
++	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
++					   !dev->dbg.sku_disable);
++#else
++	ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, true);
++#endif
++	if (ret)
++		goto out;
++
+ 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+ 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+@@ -427,6 +436,12 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
+ 		ieee80211_wake_queues(hw);
+ 	}
+ 
++	if (changed & IEEE80211_CONF_CHANGE_POWER) {
++		ret = mt7996_mcu_set_txpower_sku(phy);
++		if (ret)
++			return ret;
++	}
++
+ 	mutex_lock(&dev->mt76.mutex);
+ 
+ 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 53d2fc73..aefbdca6 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -4616,6 +4616,98 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
+ 				 &req, sizeof(req), false);
+ }
+ 
++int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
++{
++#define TX_POWER_LIMIT_TABLE_RATE	0
++#define TX_POWER_LIMIT_TABLE_PATH	1
++	struct mt7996_dev *dev = phy->dev;
++	struct mt76_phy *mphy = phy->mt76;
++	struct ieee80211_hw *hw = mphy->hw;
++	struct tx_power_limit_table_ctrl {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 power_ctrl_id;
++		u8 power_limit_type;
++		u8 band_idx;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
++		.len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4),
++		.power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
++		.power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
++		.band_idx = phy->mt76->band_idx,
++	};
++
++	int i, ret, tx_power;
++	const u8 *len = mt7996_sku_group_len;
++	struct mt76_power_limits la = {};
++	struct mt76_power_path_limits la_path = {};
++	struct sk_buff *skb;
++
++	tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
++	tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
++					      &la, &la_path, tx_power);
++	mphy->txpower_cur = tx_power;
++
++	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
++				 sizeof(req) + MT7996_SKU_PATH_NUM);
++	if (!skb)
++		return -ENOMEM;
++
++	skb_put_data(skb, &req, sizeof(req));
++	skb_put_data(skb, &la.cck, len[SKU_CCK] + len[SKU_OFDM]);
++
++	skb_put_data(skb, &la.mcs[0], len[SKU_HT20]);
++	skb_put_data(skb, &la.mcs[1], len[SKU_HT40]);
++
++	/* vht */
++	for (i = 0; i < 4; i++) {
++		skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i]));
++		skb_put_zero(skb, 2);  /* padding */
++	}
++
++	/* he */
++	skb_put_data(skb, &la.ru[0], sizeof(la.ru));
++
++	/* eht */
++	skb_put_data(skb, &la.eht_ru[0], sizeof(la.eht_ru));
++
++	/* padding */
++	skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
++
++	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
++				    MCU_WM_UNI_CMD(TXPOWER), true);
++	if (ret)
++		return ret;
++
++	/* only set per-path power table when it's configured */
++	if (!la_path.ofdm[0])
++		return 0;
++
++	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
++				 sizeof(req) + MT7996_SKU_PATH_NUM);
++	if (!skb)
++		return -ENOMEM;
++	req.power_limit_type = TX_POWER_LIMIT_TABLE_PATH;
++
++	skb_put_data(skb, &req, sizeof(req));
++	skb_put_data(skb, &la_path.cck, sizeof(la_path.cck));
++	skb_put_data(skb, &la_path.ofdm, sizeof(la_path.ofdm));
++	skb_put_data(skb, &la_path.ofdm_bf, sizeof(la_path.ofdm_bf));
++
++	for (i = 0; i < 32; i++) {
++		bool bf = i % 2;
++		u8 idx = i / 2;
++		s8 *buf = bf ? la_path.ru_bf[idx] : la_path.ru[idx];
++
++		skb_put_data(skb, buf, sizeof(la_path.ru[0]));
++	}
++
++	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
++				     MCU_WM_UNI_CMD(TXPOWER), true);
++}
++
+ #ifdef CONFIG_MTK_VENDOR
+ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+ {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index f32ac153..1d2b7c58 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -657,6 +657,18 @@ enum {
+ #define MT7996_MAX_BSS_OFFLOAD_SIZE	(MT7996_MAX_BEACON_SIZE +		\
+ 					 MT7996_BEACON_UPDATE_SIZE)
+ 
++static inline s8
++mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
++{
++	struct mt76_phy *mphy = phy->mt76;
++	int n_chains = hweight8(mphy->antenna_mask);
++
++	txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
++	txpower -= mt76_tx_power_nss_delta(n_chains);
++
++	return txpower;
++}
++
+ enum {
+ 	UNI_BAND_CONFIG_RADIO_ENABLE,
+ 	UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index abdbb1ef..d15bd950 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -61,6 +61,7 @@
+ #define MT7996_BUILD_TIME_LEN		24
+ 
+ #define MT7996_SKU_RATE_NUM		417
++#define MT7996_SKU_PATH_NUM		494
+ 
+ struct mt7996_vif;
+ struct mt7996_sta;
+@@ -610,6 +611,7 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
+ int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
+ int mt7996_mcu_apply_group_cal(struct mt7996_dev *dev);
+ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy);
++int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
+ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+ #ifdef CONFIG_NL80211_TESTMODE
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
new file mode 100644
index 0000000..c5ea448
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch
@@ -0,0 +1,107 @@
+From a048ff567915954ca9cc68ef94c9a7786542b5d9 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Wed, 3 May 2023 05:08:07 +0800
+Subject: [PATCH 1012/1015] wifi: mt76: mt7996: add vendor cmd to get available
+ color bitmap
+
+Add a vendor cmd to notify user space available color bitmap.
+The OBSS BSS color bitmap is maintained in mac80211, so mt76 will make use of that.
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ mt7996/vendor.c | 36 ++++++++++++++++++++++++++++++++++++
+ mt7996/vendor.h | 11 +++++++++++
+ 2 files changed, 47 insertions(+)
+
+diff --git a/mt7996/vendor.c b/mt7996/vendor.c
+index 8a021324..73f613aa 100644
+--- a/mt7996/vendor.c
++++ b/mt7996/vendor.c
+@@ -34,6 +34,11 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
+ 	[MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED },
+ };
+ 
++static struct nla_policy
++bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
++	[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++};
++
+ struct mt7996_amnt_data {
+ 	u8 idx;
+ 	u8 addr[ETH_ALEN];
+@@ -409,6 +414,26 @@ mt7966_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return len + 1;
+ }
+ 
++static int
++mt7996_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++				  struct sk_buff *skb, const void *data, int data_len,
++				  unsigned long *storage)
++{
++	struct ieee80211_vif *vif = wdev_to_ieee80211_vif(wdev);
++	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
++	int len = 0;
++
++	if (*storage == 1)
++		return -ENOENT;
++	*storage = 1;
++
++	if (nla_put_u64_64bit(skb, MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++			      ~bss_conf->used_color_bitmap, NL80211_ATTR_PAD))
++		return -ENOMEM;
++	len += 1;
++
++	return len;
++}
+ 
+ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 	{
+@@ -435,6 +460,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
+ 		.policy = amnt_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX,
+ 	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.dumpit = mt7996_vendor_bss_color_ctrl_dump,
++		.policy = bss_color_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++	},
+ };
+ 
+ void mt7996_vendor_register(struct mt7996_phy *phy)
+diff --git a/mt7996/vendor.h b/mt7996/vendor.h
+index 2078cafa..eec9e74a 100644
+--- a/mt7996/vendor.h
++++ b/mt7996/vendor.h
+@@ -6,6 +6,7 @@
+ enum mtk_nl80211_vendor_subcmds {
+ 	MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
+ 	MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
++	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+ 
+ enum mtk_vendor_attr_mu_ctrl {
+@@ -57,5 +58,15 @@ enum mtk_vendor_attr_mnt_dump {
+ 		NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1
+ };
+ 
++enum mtk_vendor_attr_bss_color_ctrl {
++	MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++	MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++	/* keep last */
++	NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++	MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++		NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+ 
+ #endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch
new file mode 100644
index 0000000..c01b398
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch
@@ -0,0 +1,109 @@
+From 3a58791cef81709963d654d520fab9f1b7987e7b Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 11 May 2023 09:14:28 +0800
+Subject: [PATCH 1013/1015] wifi: mt76: mt7996: get tx_retries and tx_fails
+ from txfree
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ mt7996/mac.c  | 20 +++++++++++++++-----
+ mt7996/mac.h  |  6 ++++--
+ mt7996/main.c |  6 ++++++
+ 3 files changed, 25 insertions(+), 7 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 3dc5cdae..bee4a8ae 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1240,6 +1240,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 	struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
+ 	struct mt76_txwi_cache *txwi;
+ 	struct ieee80211_sta *sta = NULL;
++	struct mt76_wcid *wcid;
+ 	LIST_HEAD(free_list);
+ 	struct sk_buff *skb, *tmp;
+ 	void *end = data + len;
+@@ -1258,7 +1259,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 		mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
+ 	}
+ 
+-	if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
++	if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
+ 		return;
+ 
+ 	total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
+@@ -1274,10 +1275,9 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 		info = le32_to_cpu(*cur_info);
+ 		if (info & MT_TXFREE_INFO_PAIR) {
+ 			struct mt7996_sta *msta;
+-			struct mt76_wcid *wcid;
+ 			u16 idx;
+ 
+-			idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
++			idx = FIELD_GET(MT_TXFREE_INFO_MLD_ID, info);
+ 			wcid = rcu_dereference(dev->mt76.wcid[idx]);
+ 			sta = wcid_to_sta(wcid);
+ 			if (!sta)
+@@ -1289,10 +1289,20 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
+ 				list_add_tail(&msta->poll_list, &dev->sta_poll_list);
+ 			spin_unlock_bh(&dev->sta_poll_lock);
+ 			continue;
+-		}
++		} else if (info & MT_TXFREE_INFO_HEADER) {
++			if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) {
++				u32 tx_retries = 0, tx_failed = 0;
++
++				tx_retries =
++					FIELD_GET(MT_TXFREE_INFO_TX_COUNT, info) - 1;
++				tx_failed = tx_retries +
++					!!FIELD_GET(MT_TXFREE_INFO_STAT, info);
+ 
+-		if (info & MT_TXFREE_INFO_HEADER)
++				wcid->stats.tx_retries += tx_retries;
++				wcid->stats.tx_failed += tx_failed;
++			}
+ 			continue;
++		}
+ 
+ 		for (i = 0; i < 2; i++) {
+ 			msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
+diff --git a/mt7996/mac.h b/mt7996/mac.h
+index bc4e6c55..74ad1e81 100644
+--- a/mt7996/mac.h
++++ b/mt7996/mac.h
+@@ -256,11 +256,13 @@ enum tx_mgnt_type {
+ #define MT_TXFREE0_MSDU_CNT		GENMASK(25, 16)
+ #define MT_TXFREE0_RX_BYTE		GENMASK(15, 0)
+ 
+-#define MT_TXFREE1_VER			GENMASK(18, 16)
++#define MT_TXFREE1_VER			GENMASK(19, 16)
+ 
+ #define MT_TXFREE_INFO_PAIR		BIT(31)
+ #define MT_TXFREE_INFO_HEADER		BIT(30)
+-#define MT_TXFREE_INFO_WLAN_ID		GENMASK(23, 12)
++#define MT_TXFREE_INFO_TX_COUNT		GENMASK(27, 24)
++#define MT_TXFREE_INFO_STAT		GENMASK(29, 28)
++#define MT_TXFREE_INFO_MLD_ID		GENMASK(23, 12)
+ #define MT_TXFREE_INFO_MSDU_ID		GENMASK(14, 0)
+ 
+ #define MT_TXS0_BW			GENMASK(31, 29)
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 71c346cb..f0bdec6b 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1024,6 +1024,12 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
+ 	sinfo->txrate.flags = txrate->flags;
+ 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ 
++	sinfo->tx_failed = msta->wcid.stats.tx_failed;
++	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
++
++	sinfo->tx_retries = msta->wcid.stats.tx_retries;
++	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
++
+ 	sinfo->ack_signal = (s8)msta->ack_signal;
+ 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
+ 
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
new file mode 100644
index 0000000..1b22e9a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch
@@ -0,0 +1,171 @@
+From 97144fb0d20ba67ec6c3a022ed5a39bc95ed40e9 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Fri, 19 May 2023 14:56:07 +0800
+Subject: [PATCH 1014/1015] wifi: mt76: mt7996: add debugfs for fw coredump.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7996/debugfs.c | 19 +++++++++++++++++--
+ mt7996/mac.c     | 28 +++++++++++++++++++++++++---
+ mt7996/mcu.h     |  4 ++++
+ mt7996/mt7996.h  | 10 ++++++++++
+ 4 files changed, 56 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 8a513f46..49c815a5 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -84,6 +84,8 @@ mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
+ 	 * 7: trigger & enable system error L4 mdp recovery.
+ 	 * 8: trigger & enable system error full recovery.
+ 	 * 9: trigger firmware crash.
++	 * 10: trigger grab wa firmware coredump.
++	 * 11: trigger grab wm firmware coredump.
+ 	 */
+ 	case UNI_CMD_SER_QUERY:
+ 		ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
+@@ -105,15 +107,25 @@ mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
+ 	/* enable full chip reset */
+ 	case UNI_CMD_SER_SET_RECOVER_FULL:
+ 		mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
+-		dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
++		dev->recovery.state |= MT_MCU_CMD_WM_WDT;
+ 		mt7996_reset(dev);
+ 		break;
+ 
+ 	/* WARNING: trigger firmware crash */
+ 	case UNI_CMD_SER_SET_SYSTEM_ASSERT:
++		// trigger wm assert exception
+ 		ret = mt7996_mcu_trigger_assert(dev);
+ 		if (ret)
+ 			return ret;
++		// trigger wa assert exception
++		mt76_wr(dev, 0x89098108, 0x20);
++		mt76_wr(dev, 0x89098118, 0x20);
++		break;
++	case UNI_CMD_SER_FW_COREDUMP_WA:
++		mt7996_coredump(dev, MT7996_COREDUMP_MANUAL_WA);
++		break;
++	case UNI_CMD_SER_FW_COREDUMP_WM:
++		mt7996_coredump(dev, MT7996_COREDUMP_MANUAL_WM);
+ 		break;
+ 	default:
+ 		break;
+@@ -160,7 +172,10 @@ mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
+ 			  "8: trigger system error full recovery\n");
+ 	desc += scnprintf(buff + desc, bufsz - desc,
+ 			  "9: trigger firmware crash\n");
+-
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "10: trigger grab wa firmware coredump\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "11: trigger grab wm firmware coredump\n");
+ 	/* SER statistics */
+ 	desc += scnprintf(buff + desc, bufsz - desc,
+ 			  "\nlet's dump firmware SER statistics...\n");
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index bee4a8ae..993b43ce 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2157,15 +2157,36 @@ void mt7996_mac_dump_work(struct work_struct *work)
+ 	struct mt7996_dev *dev;
+ 
+ 	dev = container_of(work, struct mt7996_dev, dump_work);
+-	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
++	if (dev->dump_state == MT7996_COREDUMP_MANUAL_WA ||
++	    READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
+ 		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WA);
+ 
+-	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT)
++	if (dev->dump_state == MT7996_COREDUMP_MANUAL_WM ||
++	    READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT)
+ 		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WM);
+ 
+-	queue_work(dev->mt76.wq, &dev->reset_work);
++	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK)
++		queue_work(dev->mt76.wq, &dev->reset_work);
++
++	dev->dump_state = MT7996_COREDUMP_IDLE;
+ }
+ 
++void mt7996_coredump(struct mt7996_dev *dev, u8 state)
++{
++	if (state == MT7996_COREDUMP_IDLE ||
++	    state >= __MT7996_COREDUMP_TYPE_MAX)
++		return;
++
++	if (dev->dump_state != MT7996_COREDUMP_IDLE)
++		return;
++
++	dev->dump_state = state;
++	dev_info(dev->mt76.dev, "%s attempting grab coredump\n",
++		 wiphy_name(dev->mt76.hw->wiphy));
++
++	queue_work(dev->mt76.wq, &dev->dump_work);
++ }
++
+ void mt7996_reset(struct mt7996_dev *dev)
+ {
+ 	dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n",
+@@ -2187,6 +2208,7 @@ void mt7996_reset(struct mt7996_dev *dev)
+ 
+ 		mt7996_irq_disable(dev, MT_INT_MCU_CMD);
+ 		queue_work(dev->mt76.wq, &dev->dump_work);
++		mt7996_coredump(dev, MT7996_COREDUMP_AUTO);
+ 		return;
+ 	}
+ 
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 1d2b7c58..a0cbf922 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -780,7 +780,11 @@ enum {
+ 	UNI_CMD_SER_SET_RECOVER_L3_BF,
+ 	UNI_CMD_SER_SET_RECOVER_L4_MDP,
+ 	UNI_CMD_SER_SET_RECOVER_FULL,
++	/* fw assert */
+ 	UNI_CMD_SER_SET_SYSTEM_ASSERT,
++	/* coredump */
++	UNI_CMD_SER_FW_COREDUMP_WA,
++	UNI_CMD_SER_FW_COREDUMP_WM,
+ 	/* action */
+ 	UNI_CMD_SER_ENABLE = 1,
+ 	UNI_CMD_SER_SET,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index d15bd950..e371964b 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -76,6 +76,14 @@ enum mt7996_ram_type {
+ 	__MT7996_RAM_TYPE_MAX,
+ };
+ 
++enum mt7996_coredump_state {
++	MT7996_COREDUMP_IDLE = 0,
++	MT7996_COREDUMP_MANUAL_WA,
++	MT7996_COREDUMP_MANUAL_WM,
++	MT7996_COREDUMP_AUTO,
++	__MT7996_COREDUMP_TYPE_MAX,
++};
++
+ enum mt7996_txq_id {
+ 	MT7996_TXQ_FWDL = 16,
+ 	MT7996_TXQ_MCU_WM,
+@@ -361,6 +369,7 @@ struct mt7996_dev {
+ 
+ 	/* protects coredump data */
+ 	struct mutex dump_mutex;
++	u8 dump_state;
+ #ifdef CONFIG_DEV_COREDUMP
+ 	struct {
+ 		struct mt7996_crash_data *crash_data[__MT7996_RAM_TYPE_MAX];
+@@ -540,6 +549,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
+ 			 struct ieee80211_supported_band *sband);
+ int mt7996_txbf_init(struct mt7996_dev *dev);
+ void mt7996_reset(struct mt7996_dev *dev);
++void mt7996_coredump(struct mt7996_dev *dev, u8 state);
+ int mt7996_run(struct ieee80211_hw *hw);
+ int mt7996_mcu_init(struct mt7996_dev *dev);
+ int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
new file mode 100644
index 0000000..33432ff
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch
@@ -0,0 +1,44 @@
+From 0d4c8fc47472e0acb7f823f483bc8b83c8a9f235 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Tue, 6 Jun 2023 16:57:10 +0800
+Subject: [PATCH 1015/1015] wifi: mt76: mt7996: add support for runtime set
+ in-band discovery
+
+with this patch, AP can runtime set inband discovery via hostapd_cli
+
+Usage:
+Enable FILS: hostapd_cli -i [interface] inband_discovery 2 20
+Enable UBPR: hostapd_cli -i [interface] inband_discovery 1 20
+Disable inband discovery: hostapd_cli -i [interface] inband_discovery 0 0
+
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ mt7996/mcu.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index aefbdca6..59f22f6d 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2438,8 +2438,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	if (IS_ERR(rskb))
+ 		return PTR_ERR(rskb);
+ 
+-	if (changed & BSS_CHANGED_FILS_DISCOVERY &&
+-	    vif->bss_conf.fils_discovery.max_interval) {
++	if (changed & BSS_CHANGED_FILS_DISCOVERY) {
+ 		interval = vif->bss_conf.fils_discovery.max_interval;
+ 		skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
+ 	} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
+@@ -2475,7 +2474,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 	discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
+ 	discov->tx_interval = interval;
+ 	discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
+-	discov->enable = true;
++	discov->enable = !!(interval);
+ 	discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
+ 
+ 	buf = (u8 *)tlv + sizeof(*discov);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch
new file mode 100644
index 0000000..050c6f2
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2000-wifi-mt76-rework-wed-rx-flow.patch
@@ -0,0 +1,443 @@
+From 06c6ad7b99c07aedc5403506c91cbb8e11cf95df Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 13:37:23 +0800
+Subject: [PATCH 2000/2008] wifi: mt76: rework wed rx flow
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Change-Id: Icd787345c811cb5ad30d9c7c1c5f9e5298bd3be6
+---
+ dma.c           | 89 +++++++++++++++++++++++++------------------------
+ mac80211.c      |  2 +-
+ mt76.h          | 23 ++++++++-----
+ mt7915/dma.c    |  2 --
+ mt7915/mmio.c   | 27 +++++++++++----
+ mt7915/mt7915.h |  1 +
+ tx.c            | 16 ++++-----
+ 7 files changed, 90 insertions(+), 70 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index e1e9062b..35db73b9 100644
+--- a/dma.c
++++ b/dma.c
+@@ -59,17 +59,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
+ 	return t;
+ }
+ 
+-static struct mt76_txwi_cache *
++static struct mt76_rxwi_cache *
+ mt76_alloc_rxwi(struct mt76_dev *dev)
+ {
+-	struct mt76_txwi_cache *t;
++	struct mt76_rxwi_cache *r;
+ 
+-	t = kzalloc(L1_CACHE_ALIGN(sizeof(*t)), GFP_ATOMIC);
+-	if (!t)
++	r = kzalloc(L1_CACHE_ALIGN(sizeof(*r)), GFP_ATOMIC);
++	if (!r)
+ 		return NULL;
+ 
+-	t->ptr = NULL;
+-	return t;
++	r->ptr = NULL;
++	return r;
+ }
+ 
+ static struct mt76_txwi_cache *
+@@ -88,20 +88,20 @@ __mt76_get_txwi(struct mt76_dev *dev)
+ 	return t;
+ }
+ 
+-static struct mt76_txwi_cache *
++static struct mt76_rxwi_cache *
+ __mt76_get_rxwi(struct mt76_dev *dev)
+ {
+-	struct mt76_txwi_cache *t = NULL;
++	struct mt76_rxwi_cache *r = NULL;
+ 
+-	spin_lock(&dev->wed_lock);
++	spin_lock(&dev->lock);
+ 	if (!list_empty(&dev->rxwi_cache)) {
+-		t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
++		r = list_first_entry(&dev->rxwi_cache, struct mt76_rxwi_cache,
+ 				     list);
+-		list_del(&t->list);
++		list_del(&r->list);
+ 	}
+-	spin_unlock(&dev->wed_lock);
++	spin_unlock(&dev->lock);
+ 
+-	return t;
++	return r;
+ }
+ 
+ static struct mt76_txwi_cache *
+@@ -115,13 +115,13 @@ mt76_get_txwi(struct mt76_dev *dev)
+ 	return mt76_alloc_txwi(dev);
+ }
+ 
+-struct mt76_txwi_cache *
++struct mt76_rxwi_cache *
+ mt76_get_rxwi(struct mt76_dev *dev)
+ {
+-	struct mt76_txwi_cache *t = __mt76_get_rxwi(dev);
++	struct mt76_rxwi_cache *r = __mt76_get_rxwi(dev);
+ 
+-	if (t)
+-		return t;
++	if (r)
++		return r;
+ 
+ 	return mt76_alloc_rxwi(dev);
+ }
+@@ -140,14 +140,14 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
+ EXPORT_SYMBOL_GPL(mt76_put_txwi);
+ 
+ void
+-mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
++mt76_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r)
+ {
+-	if (!t)
++	if (!r)
+ 		return;
+ 
+-	spin_lock(&dev->wed_lock);
+-	list_add(&t->list, &dev->rxwi_cache);
+-	spin_unlock(&dev->wed_lock);
++	spin_lock(&dev->lock);
++	list_add(&r->list, &dev->rxwi_cache);
++	spin_unlock(&dev->lock);
+ }
+ EXPORT_SYMBOL_GPL(mt76_put_rxwi);
+ 
+@@ -168,13 +168,13 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+ void
+ mt76_free_pending_rxwi(struct mt76_dev *dev)
+ {
+-	struct mt76_txwi_cache *t;
++	struct mt76_rxwi_cache *r;
+ 
+ 	local_bh_disable();
+-	while ((t = __mt76_get_rxwi(dev)) != NULL) {
+-		if (t->ptr)
+-			mt76_put_page_pool_buf(t->ptr, false);
+-		kfree(t);
++	while ((r = __mt76_get_rxwi(dev)) != NULL) {
++		if (r->ptr)
++			mt76_put_page_pool_buf(r->ptr, false);
++		kfree(r);
+ 	}
+ 	local_bh_enable();
+ }
+@@ -212,7 +212,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ {
+ 	struct mt76_desc *desc = &q->desc[q->head];
+ 	struct mt76_queue_entry *entry = &q->entry[q->head];
+-	struct mt76_txwi_cache *txwi = NULL;
++	struct mt76_rxwi_cache *rxwi = NULL;
+ 	u32 buf1 = 0, ctrl;
+ 	int idx = q->head;
+ 	int rx_token;
+@@ -220,13 +220,13 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ 	ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+ 
+ 	if (mt76_queue_is_wed_rx(q)) {
+-		txwi = mt76_get_rxwi(dev);
+-		if (!txwi)
++		rxwi = mt76_get_rxwi(dev);
++		if (!rxwi)
+ 			return -ENOMEM;
+ 
+-		rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr);
++		rx_token = mt76_rx_token_consume(dev, data, rxwi, buf->addr);
+ 		if (rx_token < 0) {
+-			mt76_put_rxwi(dev, txwi);
++			mt76_put_rxwi(dev, rxwi);
+ 			return -ENOMEM;
+ 		}
+ 
+@@ -241,7 +241,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ 
+ 	entry->dma_addr[0] = buf->addr;
+ 	entry->dma_len[0] = buf->len;
+-	entry->txwi = txwi;
++	entry->rxwi = rxwi;
+ 	entry->buf = data;
+ 	entry->wcid = 0xffff;
+ 	entry->skip_buf1 = true;
+@@ -404,20 +404,20 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ 	if (mt76_queue_is_wed_rx(q)) {
+ 		u32 buf1 = le32_to_cpu(desc->buf1);
+ 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
+-		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
++		struct mt76_rxwi_cache *r = mt76_rx_token_release(dev, token);
+ 
+-		if (!t)
++		if (!r)
+ 			return NULL;
+ 
+-		dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
++		dma_sync_single_for_cpu(dev->dma_dev, r->dma_addr,
+ 				SKB_WITH_OVERHEAD(q->buf_size),
+ 				page_pool_get_dma_dir(q->page_pool));
+ 
+-		buf = t->ptr;
+-		t->dma_addr = 0;
+-		t->ptr = NULL;
++		buf = r->ptr;
++		r->dma_addr = 0;
++		r->ptr = NULL;
+ 
+-		mt76_put_rxwi(dev, t);
++		mt76_put_rxwi(dev, r);
+ 
+ 		if (drop) {
+ 			u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+@@ -977,16 +977,19 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ 	mt76_for_each_q_rx(dev, i) {
+ 		struct mt76_queue *q = &dev->q_rx[i];
+ 
++		if (mt76_queue_is_wed_rx(q))
++			continue;
++
+ 		netif_napi_del(&dev->napi[i]);
+ 		mt76_dma_rx_cleanup(dev, q);
+ 
+ 		page_pool_destroy(q->page_pool);
+ 	}
+ 
+-	mt76_free_pending_txwi(dev);
+-	mt76_free_pending_rxwi(dev);
+-
+ 	if (mtk_wed_device_active(&dev->mmio.wed))
+ 		mtk_wed_device_detach(&dev->mmio.wed);
++
++	mt76_free_pending_txwi(dev);
++	mt76_free_pending_rxwi(dev);
+ }
+ EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
+diff --git a/mac80211.c b/mac80211.c
+index 6430e6ee..5a203d31 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -613,7 +613,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ 	spin_lock_init(&dev->lock);
+ 	spin_lock_init(&dev->cc_lock);
+ 	spin_lock_init(&dev->status_lock);
+-	spin_lock_init(&dev->wed_lock);
+ 	mutex_init(&dev->mutex);
+ 	init_waitqueue_head(&dev->tx_wait);
+ 
+@@ -644,6 +643,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ 	INIT_LIST_HEAD(&dev->txwi_cache);
+ 	INIT_LIST_HEAD(&dev->rxwi_cache);
+ 	dev->token_size = dev->drv->token_size;
++	dev->rx_token_size = dev->drv->rx_token_size;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
+ 		skb_queue_head_init(&dev->rx_skb[i]);
+diff --git a/mt76.h b/mt76.h
+index 8abb6f41..72c3eb8f 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -180,6 +180,7 @@ struct mt76_queue_entry {
+ 	};
+ 	union {
+ 		struct mt76_txwi_cache *txwi;
++		struct mt76_rxwi_cache *rxwi;
+ 		struct urb *urb;
+ 		int buf_sz;
+ 	};
+@@ -371,10 +372,14 @@ struct mt76_txwi_cache {
+ 	struct list_head list;
+ 	dma_addr_t dma_addr;
+ 
+-	union {
+-		struct sk_buff *skb;
+-		void *ptr;
+-	};
++	struct sk_buff *skb;
++};
++
++struct mt76_rxwi_cache {
++	struct list_head list;
++	dma_addr_t dma_addr;
++
++	void *ptr;
+ };
+ 
+ struct mt76_rx_tid {
+@@ -460,6 +465,7 @@ struct mt76_driver_ops {
+ 	u16 txwi_size;
+ 	u16 token_size;
+ 	u8 mcs_rates;
++	u16 rx_token_size;
+ 
+ 	void (*update_survey)(struct mt76_phy *phy);
+ 
+@@ -810,7 +816,6 @@ struct mt76_dev {
+ 
+ 	struct ieee80211_hw *hw;
+ 
+-	spinlock_t wed_lock;
+ 	spinlock_t lock;
+ 	spinlock_t cc_lock;
+ 
+@@ -1360,8 +1365,8 @@ mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
+ }
+ 
+ void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
+-void mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
+-struct mt76_txwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
++void mt76_put_rxwi(struct mt76_dev *dev, struct mt76_rxwi_cache *r);
++struct mt76_rxwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
+ void mt76_free_pending_rxwi(struct mt76_dev *dev);
+ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
+ 		      struct napi_struct *napi);
+@@ -1515,9 +1520,9 @@ struct mt76_txwi_cache *
+ mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
+ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
+ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+-struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
++struct mt76_rxwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
+ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
+-			  struct mt76_txwi_cache *r, dma_addr_t phys);
++			  struct mt76_rxwi_cache *r, dma_addr_t phys);
+ int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q);
+ static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
+ {
+diff --git a/mt7915/dma.c b/mt7915/dma.c
+index 86a93ded..848e9843 100644
+--- a/mt7915/dma.c
++++ b/mt7915/dma.c
+@@ -493,7 +493,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ 		    mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
+ 			dev->mt76.q_rx[MT_RXQ_MAIN].flags =
+ 				MT_WED_Q_RX(MT7915_RXQ_BAND0);
+-			dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
+ 		}
+ 
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
+@@ -530,7 +529,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ 		    mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
+ 			dev->mt76.q_rx[MT_RXQ_BAND1].flags =
+ 				MT_WED_Q_RX(MT7915_RXQ_BAND1);
+-			dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
+ 		}
+ 
+ 		/* rx data queue for band1 */
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index 984b5f60..46256842 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -600,16 +600,28 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+ 
+ 	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+ 	for (i = 0; i < dev->mt76.rx_token_size; i++) {
+-		struct mt76_txwi_cache *t;
++		struct mt76_rxwi_cache *r;
+ 
+-		t = mt76_rx_token_release(&dev->mt76, i);
+-		if (!t || !t->ptr)
++		r = mt76_rx_token_release(&dev->mt76, i);
++		if (!r || !r->ptr)
+ 			continue;
+ 
+-		mt76_put_page_pool_buf(t->ptr, false);
+-		t->ptr = NULL;
++		mt76_put_page_pool_buf(r->ptr, false);
++		r->ptr = NULL;
+ 
+-		mt76_put_rxwi(&dev->mt76, t);
++		mt76_put_rxwi(&dev->mt76, r);
++	}
++
++	mt76_for_each_q_rx(dev, i) {
++		struct mt76_queue *q = &dev->q_rx[i];
++
++		if (!mt76_queue_is_wed_rx(q))
++			continue;
++
++		netif_napi_del(&dev->napi[i]);
++		mt76_dma_rx_cleanup(dev, q);
++
++		page_pool_destroy(q->page_pool);
+ 	}
+ 
+ 	mt76_free_pending_rxwi(&dev->mt76);
+@@ -812,7 +824,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
+ 	wed->wlan.reset = mt7915_mmio_wed_reset;
+ 	wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete;
+ 
+-	dev->mt76.rx_token_size = wed->wlan.rx_npkt;
++	dev->mt76.rx_token_size += wed->wlan.rx_npkt;
+ 
+ 	if (mtk_wed_device_attach(wed))
+ 		return 0;
+@@ -1018,6 +1030,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
+ 				SURVEY_INFO_TIME_RX |
+ 				SURVEY_INFO_TIME_BSS_RX,
+ 		.token_size = MT7915_TOKEN_SIZE,
++		.rx_token_size = MT7915_RX_TOKEN_SIZE;
+ 		.tx_prepare_skb = mt7915_tx_prepare_skb,
+ 		.tx_complete_skb = mt76_connac_tx_complete_skb,
+ 		.rx_skb = mt7915_queue_rx_skb,
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 103cd0d7..8ee62f63 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -62,6 +62,7 @@
+ #define MT7915_EEPROM_BLOCK_SIZE	16
+ #define MT7915_HW_TOKEN_SIZE		4096
+ #define MT7915_TOKEN_SIZE		8192
++#define MT7915_RX_TOKEN_SIZE		4096
+ 
+ #define MT7915_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */
+ #define MT7915_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
+diff --git a/tx.c b/tx.c
+index 72b3ec71..6cb71f34 100644
+--- a/tx.c
++++ b/tx.c
+@@ -761,16 +761,16 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+ EXPORT_SYMBOL_GPL(mt76_token_consume);
+ 
+ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
+-			  struct mt76_txwi_cache *t, dma_addr_t phys)
++			  struct mt76_rxwi_cache *r, dma_addr_t phys)
+ {
+ 	int token;
+ 
+ 	spin_lock_bh(&dev->rx_token_lock);
+-	token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size,
++	token = idr_alloc(&dev->rx_token, r, 0, dev->rx_token_size,
+ 			  GFP_ATOMIC);
+ 	if (token >= 0) {
+-		t->ptr = ptr;
+-		t->dma_addr = phys;
++		r->ptr = ptr;
++		r->dma_addr = phys;
+ 	}
+ 	spin_unlock_bh(&dev->rx_token_lock);
+ 
+@@ -807,15 +807,15 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
+ }
+ EXPORT_SYMBOL_GPL(mt76_token_release);
+ 
+-struct mt76_txwi_cache *
++struct mt76_rxwi_cache *
+ mt76_rx_token_release(struct mt76_dev *dev, int token)
+ {
+-	struct mt76_txwi_cache *t;
++	struct mt76_rxwi_cache *r;
+ 
+ 	spin_lock_bh(&dev->rx_token_lock);
+-	t = idr_remove(&dev->rx_token, token);
++	r = idr_remove(&dev->rx_token, token);
+ 	spin_unlock_bh(&dev->rx_token_lock);
+ 
+-	return t;
++	return r;
+ }
+ EXPORT_SYMBOL_GPL(mt76_rx_token_release);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0022-mt76-revert-page-pool-changes.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
similarity index 83%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0022-mt76-revert-page-pool-changes.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
index f0daca8..58605d3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0022-mt76-revert-page-pool-changes.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch
@@ -1,44 +1,47 @@
-From d28a3716f729848ef65192c84411b0912afe70c6 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Mon, 6 Feb 2023 15:34:43 +0800
-Subject: [PATCH 22/22] mt76: revert page pool changes
+From 15b04fc966aa8f30492726132a6b81466b187581 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 19:49:22 +0800
+Subject: [PATCH 2001/2008] wifi: mt76: revert page_poll for kernel 5.4
 
+This reverts commit e8c10835cf062c577ddf426913788c39d30b4bd7.
+
+Change-Id: I4e5764fc545087f691fb4c2f43e7a9cefd1e1657
 ---
- dma.c         | 72 ++++++++++++++++++++++++++-------------------------
- mac80211.c    | 57 ----------------------------------------
- mt76.h        | 22 +---------------
- mt7915/main.c | 26 +++++++------------
- mt7915/mmio.c | 55 ++++++++++++++++++++++++---------------
- mt7921/main.c | 31 +++-------------------
- usb.c         | 43 +++++++++++++++---------------
- 7 files changed, 108 insertions(+), 198 deletions(-)
+ dma.c         | 78 +++++++++++++++++++++++++++++----------------------
+ mac80211.c    | 57 -------------------------------------
+ mt76.h        | 22 +--------------
+ mt7915/main.c | 26 +++++++----------
+ mt7915/mmio.c | 55 ++++++++++++++++++++++--------------
+ mt7921/main.c | 31 +++-----------------
+ usb.c         | 43 ++++++++++++++--------------
+ 7 files changed, 115 insertions(+), 197 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 465190eb..f560d37d 100644
+index 35db73b9..7153be47 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
  	local_bh_disable();
- 	while ((t = __mt76_get_rxwi(dev)) != NULL) {
- 		if (t->ptr)
--			mt76_put_page_pool_buf(t->ptr, false);
-+			skb_free_frag(t->ptr);
- 		kfree(t);
+ 	while ((r = __mt76_get_rxwi(dev)) != NULL) {
+ 		if (r->ptr)
+-			mt76_put_page_pool_buf(r->ptr, false);
++			skb_free_frag(r->ptr);
+ 		kfree(r);
  	}
  	local_bh_enable();
 @@ -409,9 +409,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- 		if (!t)
+ 		if (!r)
  			return NULL;
  
--		dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
+-		dma_sync_single_for_cpu(dev->dma_dev, r->dma_addr,
 -				SKB_WITH_OVERHEAD(q->buf_size),
 -				page_pool_get_dma_dir(q->page_pool));
-+		dma_unmap_single(dev->dma_dev, t->dma_addr,
++		dma_unmap_single(dev->dma_dev, r->dma_addr,
 +				 SKB_WITH_OVERHEAD(q->buf_size),
 +				 DMA_FROM_DEVICE);
  
- 		buf = t->ptr;
- 		t->dma_addr = 0;
+ 		buf = r->ptr;
+ 		r->dma_addr = 0;
 @@ -430,9 +430,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  	} else {
  		buf = e->buf;
@@ -52,7 +55,7 @@
  	}
  
  	return buf;
-@@ -586,11 +586,11 @@ free_skb:
+@@ -592,11 +592,11 @@ free_skb:
  }
  
  static int
@@ -67,7 +70,7 @@
  
  	if (!q->ndesc)
  		return 0;
-@@ -598,25 +598,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -604,25 +604,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
  	spin_lock_bh(&q->lock);
  
  	while (q->queued < q->ndesc - 1) {
@@ -75,8 +78,7 @@
  		struct mt76_queue_buf qbuf;
 -		dma_addr_t addr;
 -		int offset;
--		void *buf;
-+		void *buf = NULL;
+ 		void *buf;
  
 -		buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
 +		buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
@@ -105,7 +107,7 @@
  			break;
  		}
  		frames++;
-@@ -660,7 +661,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -666,7 +667,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
  		/* WED txfree queue needs ring to be initialized before setup */
  		q->flags = 0;
  		mt76_dma_queue_reset(dev, q);
@@ -114,7 +116,7 @@
  		q->flags = flags;
  
  		ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -708,10 +709,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -714,10 +715,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  	if (!q->entry)
  		return -ENOMEM;
  
@@ -125,7 +127,7 @@
  	ret = mt76_dma_wed_setup(dev, q, false);
  	if (ret)
  		return ret;
-@@ -725,6 +722,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -731,6 +728,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  static void
  mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  {
@@ -133,20 +135,28 @@
  	void *buf;
  	bool more;
  
-@@ -738,7 +736,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -744,7 +742,10 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  		if (!buf)
  			break;
  
 -		mt76_put_page_pool_buf(buf, false);
++		if (q->flags & MT_QFLAG_RRO)
++			continue;
++
 +		skb_free_frag(buf);
  	} while (1);
  
  	if (q->rx_head) {
-@@ -747,6 +745,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -753,6 +754,18 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  	}
  
  	spin_unlock_bh(&q->lock);
 +
++	if (((q->flags & MT_QFLAG_WED) &&
++	     FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) ||
++	    (q->flags & MT_QFLAG_RRO))
++		return;
++
 +	if (!q->rx_page.va)
 +		return;
 +
@@ -156,7 +166,7 @@
  }
  
  static void
-@@ -767,7 +772,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -773,7 +786,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
  	mt76_dma_wed_setup(dev, q, true);
  	if (q->flags != MT_WED_Q_TXFREE) {
  		mt76_dma_sync_idx(dev, q);
@@ -165,7 +175,7 @@
  	}
  }
  
-@@ -785,7 +790,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -791,7 +804,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
  
  		skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
  	} else {
@@ -174,7 +184,7 @@
  	}
  
  	if (more)
-@@ -858,7 +863,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -864,7 +877,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  			goto free_frag;
  
  		skb_reserve(skb, q->buf_offset);
@@ -182,7 +192,7 @@
  
  		*(u32 *)skb->cb = info;
  
-@@ -874,10 +878,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -880,10 +892,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		continue;
  
  free_frag:
@@ -195,7 +205,7 @@
  	return done;
  }
  
-@@ -922,7 +926,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -928,7 +940,7 @@ mt76_dma_init(struct mt76_dev *dev,
  
  	mt76_for_each_q_rx(dev, i) {
  		netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -204,7 +214,7 @@
  		napi_enable(&dev->napi[i]);
  	}
  
-@@ -973,8 +977,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -982,8 +994,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
  
  		netif_napi_del(&dev->napi[i]);
  		mt76_dma_rx_cleanup(dev, q);
@@ -212,9 +222,9 @@
 -		page_pool_destroy(q->page_pool);
  	}
  
- 	mt76_free_pending_txwi(dev);
+ 	if (mtk_wed_device_active(&dev->mmio.wed))
 diff --git a/mac80211.c b/mac80211.c
-index d1cdaee8..4599f697 100644
+index 5a203d31..f7578308 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -4,7 +4,6 @@
@@ -224,8 +234,8 @@
 -#include <net/page_pool.h>
  #include "mt76.h"
  
- #define CHAN2G(_idx, _freq) {			\
-@@ -562,47 +561,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+ static const struct ieee80211_channel mt76_channels_2ghz[] = {
+@@ -542,47 +541,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
  }
  EXPORT_SYMBOL_GPL(mt76_unregister_phy);
  
@@ -273,7 +283,7 @@
  struct mt76_dev *
  mt76_alloc_device(struct device *pdev, unsigned int size,
  		  const struct ieee80211_ops *ops,
-@@ -1748,21 +1706,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1728,21 +1686,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  }
  EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
  
@@ -296,10 +306,10 @@
  {
  	struct ieee80211_hw *hw = phy->hw;
 diff --git a/mt76.h b/mt76.h
-index 31d5dc37..f012ac0c 100644
+index 72c3eb8f..a0c20d36 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -202,7 +202,7 @@ struct mt76_queue {
+@@ -224,7 +224,7 @@ struct mt76_queue {
  
  	dma_addr_t desc_dma;
  	struct sk_buff *rx_head;
@@ -308,7 +318,7 @@
  };
  
  struct mt76_mcu_ops {
-@@ -1363,7 +1363,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+@@ -1410,7 +1410,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
  	return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
  }
  
@@ -316,10 +326,10 @@
  void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  			 struct mt76_sta_stats *stats, bool eht);
  int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
-@@ -1475,25 +1474,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
- struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
+@@ -1523,25 +1522,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+ struct mt76_rxwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
  int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
- 			  struct mt76_txwi_cache *r, dma_addr_t phys);
+ 			  struct mt76_rxwi_cache *r, dma_addr_t phys);
 -int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q);
 -static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
 -{
@@ -401,7 +411,7 @@
  
  static void
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 984b5f60..1bb8a4cb 100644
+index 46256842..8ff2c70c 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -596,9 +596,13 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
@@ -416,20 +426,20 @@
 +				sizeof(struct skb_shared_info));
 +
  	for (i = 0; i < dev->mt76.rx_token_size; i++) {
- 		struct mt76_txwi_cache *t;
+ 		struct mt76_rxwi_cache *r;
  
 @@ -606,7 +610,9 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
- 		if (!t || !t->ptr)
+ 		if (!r || !r->ptr)
  			continue;
  
--		mt76_put_page_pool_buf(t->ptr, false);
-+		dma_unmap_single(dev->mt76.dma_dev, t->dma_addr,
+-		mt76_put_page_pool_buf(r->ptr, false);
++		dma_unmap_single(dev->mt76.dma_dev, r->dma_addr,
 +				 wed->wlan.rx_size, DMA_FROM_DEVICE);
-+		__free_pages(virt_to_page(t->ptr), get_order(length));
- 		t->ptr = NULL;
++		__free_pages(virt_to_page(r->ptr), get_order(length));
+ 		r->ptr = NULL;
  
- 		mt76_put_rxwi(&dev->mt76, t);
-@@ -618,38 +624,47 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
+ 		mt76_put_rxwi(&dev->mt76, r);
+@@ -630,38 +636,47 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
  static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
  {
  	struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
@@ -450,7 +460,7 @@
 -		enum dma_data_direction dir;
 -		dma_addr_t addr;
 -		u32 offset;
-+		struct mt76_txwi_cache *t = mt76_get_rxwi(&dev->mt76);
++		struct mt76_rxwi_cache *r = mt76_get_rxwi(&dev->mt76);
 +		dma_addr_t phy_addr;
 +		struct page *page;
  		int token;
@@ -465,7 +475,7 @@
 -		if (!buf)
 +		page = __dev_alloc_pages(GFP_KERNEL, get_order(length));
 +		if (!page) {
-+			mt76_put_rxwi(&dev->mt76, t);
++			mt76_put_rxwi(&dev->mt76, r);
  			goto unmap;
 +		}
  
@@ -478,24 +488,24 @@
 +					  DMA_TO_DEVICE);
 +		if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
 +			__free_pages(page, get_order(length));
-+			mt76_put_rxwi(&dev->mt76, t);
++			mt76_put_rxwi(&dev->mt76, r);
 +			goto unmap;
 +		}
  
 -		desc->buf0 = cpu_to_le32(addr);
 -		token = mt76_rx_token_consume(&dev->mt76, buf, t, addr);
 +		desc->buf0 = cpu_to_le32(phy_addr);
-+		token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr);
++		token = mt76_rx_token_consume(&dev->mt76, ptr, r, phy_addr);
  		if (token < 0) {
 -			mt76_put_page_pool_buf(buf, false);
 +			dma_unmap_single(dev->mt76.dma_dev, phy_addr,
 +					 wed->wlan.rx_size, DMA_TO_DEVICE);
 +			__free_pages(page, get_order(length));
-+			mt76_put_rxwi(&dev->mt76, t);
++			mt76_put_rxwi(&dev->mt76, r);
  			goto unmap;
  		}
  
-@@ -661,8 +676,6 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+@@ -673,8 +688,6 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
  	return 0;
  
  unmap:
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
new file mode 100644
index 0000000..21f5e83
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch
@@ -0,0 +1,38 @@
+From 2ced3e3d33ef919332226f09a214ef2b04555a6d Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Wed, 19 Apr 2023 17:13:41 +0800
+Subject: [PATCH 2002/2008] wifi: mt76: wed: change wed token init size to
+ adapt wed3.0
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ tx.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/tx.c b/tx.c
+index 6cb71f34..618c99a1 100644
+--- a/tx.c
++++ b/tx.c
+@@ -737,12 +737,16 @@ EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked);
+ 
+ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+ {
+-	int token;
++	int token, start = 0;
++
++	if (mtk_wed_device_active(&dev->mmio.wed))
++		start = dev->mmio.wed.wlan.nbuf;
+ 
+ 	spin_lock_bh(&dev->token_lock);
+ 
+-	token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
+-	if (token >= 0)
++	token = idr_alloc(&dev->token, *ptxwi, start, start + dev->token_size,
++			  GFP_ATOMIC);
++	if (token >= start)
+ 		dev->token_count++;
+ 
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch
new file mode 100644
index 0000000..feb77a6
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch
@@ -0,0 +1,995 @@
+From d9167faacb2a8466e2d19993f29b2c0770c5164e Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Wed, 26 Apr 2023 16:44:57 +0800
+Subject: [PATCH 2003/2008] wifi: mt76: mt7996: wed: add wed3.0 tx support
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c           |  17 ++-
+ mt76.h          |   7 ++
+ mt7996/dma.c    | 128 ++++++++++++++++++---
+ mt7996/init.c   |  21 +++-
+ mt7996/mac.c    |  29 ++++-
+ mt7996/main.c   |  46 ++++++++
+ mt7996/mmio.c   | 295 +++++++++++++++++++++++++++++++++++++++++++++---
+ mt7996/mt7996.h |   8 +-
+ mt7996/pci.c    |  72 +++++++++---
+ mt7996/regs.h   |   5 +
+ 10 files changed, 567 insertions(+), 61 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 7153be47..930ec768 100644
+--- a/dma.c
++++ b/dma.c
+@@ -13,6 +13,11 @@
+ 	u32 _offset = offsetof(struct mt76_queue_regs, _field);		\
+ 	u32 _val;							\
+ 	if ((_q)->flags & MT_QFLAG_WED)					\
++		if((_q)->flags & MT_QFLAG_WED_EXT)			\
++		_val = mtk_wed_device_reg_read(&(_dev)->mmio.wed_ext,	\
++					       ((_q)->wed_regs +	\
++					        _offset));		\
++		else							\
+ 		_val = mtk_wed_device_reg_read(&(_dev)->mmio.wed,	\
+ 					       ((_q)->wed_regs +	\
+ 					        _offset));		\
+@@ -24,6 +29,11 @@
+ #define Q_WRITE(_dev, _q, _field, _val)	do {				\
+ 	u32 _offset = offsetof(struct mt76_queue_regs, _field);		\
+ 	if ((_q)->flags & MT_QFLAG_WED)					\
++		if((_q)->flags & MT_QFLAG_WED_EXT)			\
++		mtk_wed_device_reg_write(&(_dev)->mmio.wed_ext,		\
++					 ((_q)->wed_regs + _offset),	\
++					 _val);				\
++		else							\
+ 		mtk_wed_device_reg_write(&(_dev)->mmio.wed,		\
+ 					 ((_q)->wed_regs + _offset),	\
+ 					 _val);				\
+@@ -654,6 +664,9 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ 	if (!(q->flags & MT_QFLAG_WED))
+ 		return 0;
+ 
++	if ((q->flags & MT_QFLAG_WED_EXT))
++		wed = &dev->mmio.wed_ext;
++
+ 	type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
+ 	ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
+ 
+@@ -719,7 +732,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ 	if (ret)
+ 		return ret;
+ 
+-	if (q->flags != MT_WED_Q_TXFREE)
++	if (!mt76_queue_is_txfree(q))
+ 		mt76_dma_queue_reset(dev, q);
+ 
+ 	return 0;
+@@ -999,6 +1012,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ 	if (mtk_wed_device_active(&dev->mmio.wed))
+ 		mtk_wed_device_detach(&dev->mmio.wed);
+ 
++	if (mtk_wed_device_active(&dev->mmio.wed_ext))
++		mtk_wed_device_detach(&dev->mmio.wed_ext);
+ 	mt76_free_pending_txwi(dev);
+ 	mt76_free_pending_rxwi(dev);
+ }
+diff --git a/mt76.h b/mt76.h
+index a0c20d36..ee0dbdd7 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -51,6 +51,7 @@
+ #define MT_QFLAG_WED_RING	GENMASK(1, 0)
+ #define MT_QFLAG_WED_TYPE	GENMASK(3, 2)
+ #define MT_QFLAG_WED		BIT(4)
++#define MT_QFLAG_WED_EXT	BIT(11)
+ 
+ #define __MT_WED_Q(_type, _n)	(MT_QFLAG_WED | \
+ 				 FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
+@@ -623,6 +624,7 @@ struct mt76_mmio {
+ 	u32 irqmask;
+ 
+ 	struct mtk_wed_device wed;
++	struct mtk_wed_device wed_ext;
+ 	struct completion wed_reset;
+ 	struct completion wed_reset_complete;
+ };
+@@ -1514,6 +1516,11 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
+ 	return (q->flags & MT_QFLAG_WED) &&
+ 	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
+ }
++static inline bool mt76_queue_is_txfree(struct mt76_queue *q)
++{
++	return (q->flags & MT_QFLAG_WED) &&
++	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
++}
+ 
+ struct mt76_txwi_cache *
+ mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index b8f253d0..673b08bb 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -7,6 +7,25 @@
+ #include "../dma.h"
+ #include "mac.h"
+ 
++int
++mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
++		     int ring_base, struct mtk_wed_device *wed)
++{
++	struct mt7996_dev *dev = phy->dev;
++	u32 flags = 0;
++
++	if (mtk_wed_device_active(wed)) {
++		ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
++		idx -= MT_TXQ_ID(0);
++		flags = MT_WED_Q_TX(idx);
++		if (phy->mt76->band_idx == MT_BAND2)
++			flags = MT_QFLAG_WED_EXT | MT_WED_Q_TX(0) ;
++	}
++
++	return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc,
++					  ring_base, flags);
++}
++
+ static int mt7996_poll_tx(struct napi_struct *napi, int budget)
+ {
+ 	struct mt7996_dev *dev;
+@@ -128,7 +147,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
+ 	}
+ }
+ 
+-void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
++void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ {
+ 	u32 hif1_ofs = 0;
+ 	u32 irq_mask;
+@@ -153,11 +172,9 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 	}
+ 
+ 	/* enable interrupts for TX/RX rings */
+-	irq_mask = MT_INT_MCU_CMD;
+-	if (reset)
+-		goto done;
+-
+-	irq_mask |= (MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU);
++	irq_mask = MT_INT_MCU_CMD |
++			   MT_INT_RX_DONE_MCU |
++			   MT_INT_TX_DONE_MCU;
+ 
+ 	if (mt7996_band_valid(dev, MT_BAND0))
+ 		irq_mask |= MT_INT_BAND0_RX_DONE;
+@@ -168,7 +185,18 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 	if (mt7996_band_valid(dev, MT_BAND2))
+ 		irq_mask |= MT_INT_BAND2_RX_DONE;
+ 
+-done:
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) {
++		u32 wed_irq_mask = irq_mask;
++
++		wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
++
++		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
++
++		mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
++	}
++
++	irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
++
+ 	mt7996_irq_enable(dev, irq_mask);
+ 	mt7996_irq_disable(dev, 0);
+ }
+@@ -241,19 +269,24 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 		/* fix hardware limitation, pcie1's rx ring3 is not available
+ 		 * so, redirect pcie0 rx ring3 interrupt to pcie1
+ 		 */
+-		mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
+-			 MT_WFDMA0_RX_INT_SEL_RING3);
+-
+-		/* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->rro_support)
++			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
++				 MT_WFDMA0_RX_INT_SEL_RING6);
++		else
++			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
++				 MT_WFDMA0_RX_INT_SEL_RING3);
+ 	}
+ 
+-	__mt7996_dma_enable(dev, reset);
++	__mt7996_dma_enable(dev, reset, true);
+ 
+ 	return 0;
+ }
+ 
+ int mt7996_dma_init(struct mt7996_dev *dev)
+ {
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++	struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
++	u32 rx_base;
+ 	u32 hif1_ofs = 0;
+ 	int ret;
+ 
+@@ -267,10 +300,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	mt7996_dma_disable(dev, true);
+ 
+ 	/* init tx queue */
+-	ret = mt76_connac_init_tx_queues(dev->phy.mt76,
+-					 MT_TXQ_ID(dev->mphy.band_idx),
+-					 MT7996_TX_RING_SIZE,
+-					 MT_TXQ_RING_BASE(0), 0);
++	ret = mt7996_init_tx_queues(&dev->phy,
++				    MT_TXQ_ID(dev->mphy.band_idx),
++				    MT7996_TX_RING_SIZE,
++				    MT_TXQ_RING_BASE(0),
++				    wed);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -326,6 +360,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 		return ret;
+ 
+ 	/* tx free notify event from WA for band0 */
++	if (mtk_wed_device_active(wed) && !dev->rro_support)
++		dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
++
+ 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
+ 			       MT_RXQ_ID(MT_RXQ_MAIN_WA),
+ 			       MT7996_RX_MCU_RING_SIZE,
+@@ -336,17 +373,24 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 
+ 	if (mt7996_band_valid(dev, MT_BAND2)) {
+ 		/* rx data queue for band2 */
++		rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
++		if (mtk_wed_device_active(wed))
++			rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
++
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ 				       MT_RXQ_ID(MT_RXQ_BAND2),
+ 				       MT7996_RX_RING_SIZE,
+ 				       MT_RX_BUF_SIZE,
+-				       MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs);
++				       rx_base);
+ 		if (ret)
+ 			return ret;
+ 
+ 		/* tx free notify event from WA for band2
+ 		 * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
+ 		 */
++		if (mtk_wed_device_active(wed_ext) && !dev->rro_support)
++			dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE |
++								MT_QFLAG_WED_EXT;
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2_WA],
+ 				       MT_RXQ_ID(MT_RXQ_BAND2_WA),
+ 				       MT7996_RX_MCU_RING_SIZE,
+@@ -356,6 +400,56 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 			return ret;
+ 	}
+ 
++
++	if (dev->rro_support) {
++		/* rx rro data queue for band0 */
++		dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags = MT_RRO_Q_DATA(0);
++		dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_QFLAG_MAGIC;
++		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
++				       MT_RXQ_ID(MT_RXQ_RRO_BAND0),
++				       MT7996_RX_RING_SIZE,
++				       MT7996_RX_BUF_SIZE,
++				       MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0));
++		if (ret)
++			return ret;
++
++		/* tx free notify event from WA for band0 */
++		if (mtk_wed_device_active(wed))
++			dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
++		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
++				       MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
++				       MT7996_RX_MCU_RING_SIZE,
++				       MT7996_RX_BUF_SIZE,
++				       MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
++		if (ret)
++			return ret;
++
++		if (mt7996_band_valid(dev, MT_BAND2)) {
++			/* rx rro data queue for band2 */
++			dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags = MT_RRO_Q_DATA(1);
++			dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_QFLAG_MAGIC;
++			ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
++					       MT_RXQ_ID(MT_RXQ_RRO_BAND2),
++					       MT7996_RX_RING_SIZE,
++					       MT7996_RX_BUF_SIZE,
++					       MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
++			if (ret)
++				return ret;
++
++			/* tx free notify event from MAC for band2 */
++			if (mtk_wed_device_active(wed_ext))
++				dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE |
++									    MT_QFLAG_WED_EXT;
++			ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2],
++					       MT_RXQ_ID(MT_RXQ_TXFREE_BAND2),
++					       MT7996_RX_MCU_RING_SIZE,
++					       MT7996_RX_BUF_SIZE,
++					       MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs);
++			if (ret)
++				return ret;
++		}
++	}
++
+ 	ret = mt76_init_queues(dev, mt76_dma_rx_poll);
+ 	if (ret < 0)
+ 		return ret;
+diff --git a/mt7996/init.c b/mt7996/init.c
+index a6caf4f1..6cfbc50d 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -534,6 +534,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	struct mt76_phy *mphy;
+ 	u32 mac_ofs, hif1_ofs = 0;
+ 	int ret;
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ 
+ 	if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
+ 		return 0;
+@@ -541,8 +542,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	if (phy)
+ 		return 0;
+ 
+-	if (band == MT_BAND2 && dev->hif2)
++	if (band == MT_BAND2 && dev->hif2) {
+ 		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++		wed = &dev->mt76.mmio.wed_ext;
++	}
+ 
+ 	mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band);
+ 	if (!mphy)
+@@ -576,10 +579,11 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 
+ 	/* init wiphy according to mphy and phy */
+ 	mt7996_init_wiphy(mphy->hw);
+-	ret = mt76_connac_init_tx_queues(phy->mt76,
+-					 MT_TXQ_ID(band),
+-					 MT7996_TX_RING_SIZE,
+-					 MT_TXQ_RING_BASE(band) + hif1_ofs, 0);
++	ret = mt7996_init_tx_queues(mphy->priv,
++				    MT_TXQ_ID(band),
++				    MT7996_TX_RING_SIZE,
++				    MT_TXQ_RING_BASE(band) + hif1_ofs,
++				    wed);
+ 	if (ret)
+ 		goto error;
+ 
+@@ -1119,6 +1123,13 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 
+ 	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+ 
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
++		mt76_wr(dev, MT_INT1_MASK_CSR,
++			dev->mt76.mmio.irqmask|MT_INT_TX_DONE_BAND2);
++		mtk_wed_device_start(&dev->mt76.mmio.wed_ext,
++				     dev->mt76.mmio.irqmask |MT_INT_TX_DONE_BAND2);
++	}
++
+ 	dev->recovery.hw_init_done = true;
+ 
+ 	ret = mt7996_init_debugfs(&dev->phy);
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 993b43ce..fc2d9269 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1175,6 +1175,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 	return 0;
+ }
+ 
++u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
++{
++	struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE;
++	__le32 *txwi = ptr;
++	u32 val;
++
++	memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
++
++	val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
++	      FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
++	txwi[0] = cpu_to_le32(val);
++
++	val = BIT(31) |
++	      FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
++	txwi[1] = cpu_to_le32(val);
++
++	txp->token = cpu_to_le16(token_id);
++	txp->nbuf = 1;
++	txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
++
++	return MT_TXD_SIZE + sizeof(*txp);
++}
++
+ static void
+ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+ {
+@@ -1561,6 +1584,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 
+ 	switch (type) {
+ 	case PKT_TYPE_TXRX_NOTIFY:
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext) &&
++		    q == MT_RXQ_TXFREE_BAND2)
++		    return;
++
+ 		mt7996_mac_tx_free(dev, skb->data, skb->len);
+ 		napi_consume_skb(skb, 1);
+ 		break;
+@@ -2035,7 +2062,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
+ 
+ 	/* enable dma tx/rx and interrupt */
+-	__mt7996_dma_enable(dev, false);
++	__mt7996_dma_enable(dev, false, false);
+ 
+ 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	clear_bit(MT76_RESET, &dev->mphy.state);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index f0bdec6b..50fa6523 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1405,6 +1405,49 @@ out:
+ 	return ret;
+ }
+ 
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static int
++mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
++			     struct ieee80211_vif *vif,
++			     struct ieee80211_sta *sta,
++			     struct net_device_path_ctx *ctx,
++			     struct net_device_path *path)
++{
++	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
++	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++	struct mt7996_dev *dev = mt7996_hw_dev(hw);
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++
++	if(phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
++		wed = &dev->mt76.mmio.wed_ext;
++
++	if (!mtk_wed_device_active(wed))
++		return -ENODEV;
++
++	if (msta->wcid.idx > MT7996_WTBL_STA)
++		return -EIO;
++
++	path->type = DEV_PATH_MTK_WDMA;
++	path->dev = ctx->dev;
++	path->mtk_wdma.wdma_idx = wed->wdma_idx;
++	path->mtk_wdma.bss = mvif->mt76.idx;
++	path->mtk_wdma.queue = 0;
++	path->mtk_wdma.wcid = msta->wcid.idx;
++
++	/* pao info */
++	if (mtk_wed_device_support_pao(wed)) {
++		path->mtk_wdma.amsdu_en = 1;
++		path->mtk_wdma.is_sp = 0;
++		path->mtk_wdma.is_fixedrate = 0;
++	}
++	ctx->dev = NULL;
++
++	return 0;
++}
++
++#endif
++
+ const struct ieee80211_ops mt7996_ops = {
+ 	.tx = mt7996_tx,
+ 	.start = mt7996_start,
+@@ -1451,4 +1494,7 @@ const struct ieee80211_ops mt7996_ops = {
+ 	.sta_add_debugfs = mt7996_sta_add_debugfs,
+ #endif
+ 	.set_radar_background = mt7996_set_radar_background,
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++	.net_fill_forward_path = mt7996_net_fill_forward_path,
++#endif
+ };
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 3a591a7b..b9e47e73 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -10,6 +10,11 @@
+ #include "mt7996.h"
+ #include "mac.h"
+ #include "../trace.h"
++#include "../dma.h"
++
++
++static bool wed_enable = true;
++module_param(wed_enable, bool, 0644);
+ 
+ static const struct __base mt7996_reg_base[] = {
+ 	[WF_AGG_BASE]		= { { 0x820e2000, 0x820f2000, 0x830e2000 } },
+@@ -191,6 +196,228 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ 	return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
+ }
+ 
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static void mt7996_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
++{
++	struct mt7996_dev *dev;
++	struct page *page;
++	int i;
++
++	dev = container_of(wed, struct mt7996_dev, mt76.mmio.wed);
++	for (i = 0; i < dev->mt76.rx_token_size; i++) {
++		struct mt76_rxwi_cache *r;
++
++		r = mt76_rx_token_release(&dev->mt76, i);
++		if (!r || !r->ptr)
++			continue;
++
++		dma_unmap_single(dev->mt76.dma_dev, r->dma_addr,
++				 wed->wlan.rx_size, DMA_FROM_DEVICE);
++		skb_free_frag(r->ptr);
++		r->ptr = NULL;
++
++		mt76_put_rxwi(&dev->mt76, r);
++	}
++
++	mt76_free_pending_rxwi(&dev->mt76);
++
++	mt76_for_each_q_rx(&dev->mt76, i) {
++		struct mt76_queue *q = &dev->mt76.q_rx[i];
++
++		if (mt76_queue_is_wed_rx(q)) {
++			if (!q->rx_page.va)
++				continue;
++
++			page = virt_to_page(q->rx_page.va);
++			__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
++			memset(&q->rx_page, 0, sizeof(q->rx_page));
++		}
++	}
++
++	if (!wed->rx_buf_ring.rx_page.va)
++		return;
++
++	page = virt_to_page(wed->rx_buf_ring.rx_page.va);
++	__page_frag_cache_drain(page, wed->rx_buf_ring.rx_page.pagecnt_bias);
++	memset(&wed->rx_buf_ring.rx_page, 0, sizeof(wed->rx_buf_ring.rx_page));
++
++}
++
++static u32 mt7996_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
++{
++	struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc;
++	struct mt7996_dev *dev;
++	u32 length;
++	int i;
++
++	dev = container_of(wed, struct mt7996_dev, mt76.mmio.wed);
++	length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
++				sizeof(struct skb_shared_info));
++
++	for (i = 0; i < size; i++) {
++		struct mt76_rxwi_cache *r = mt76_get_rxwi(&dev->mt76);
++		dma_addr_t phy_addr;
++		int token;
++		void *ptr;
++
++		ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length,
++				      GFP_KERNEL);
++		if (!ptr) {
++			mt76_put_rxwi(&dev->mt76, r);
++			goto unmap;
++		}
++
++		phy_addr = dma_map_single(dev->mt76.dma_dev, ptr,
++					  wed->wlan.rx_size,
++					  DMA_TO_DEVICE);
++		if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
++			skb_free_frag(ptr);
++			mt76_put_rxwi(&dev->mt76, r);
++			goto unmap;
++		}
++
++		desc->buf0 = cpu_to_le32(phy_addr);
++		token = mt76_rx_token_consume(&dev->mt76, ptr, r, phy_addr);
++		if (token < 0) {
++			dma_unmap_single(dev->mt76.dma_dev, phy_addr,
++					 wed->wlan.rx_size, DMA_TO_DEVICE);
++			skb_free_frag(ptr);
++			mt76_put_rxwi(&dev->mt76, r);
++			goto unmap;
++		}
++
++		desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
++						      token));
++		desc++;
++	}
++
++	return 0;
++
++unmap:
++	mt7996_mmio_wed_release_rx_buf(wed);
++	return -ENOMEM;
++}
++#endif
++
++int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
++			 bool hif2, int *irq)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++	struct pci_dev *pci_dev = pdev_ptr;
++	u32 hif1_ofs = 0;
++	int ret;
++
++	if (!wed_enable)
++		return 0;
++
++	dev->rro_support = true;
++
++	hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++
++	if (hif2)
++		wed = &dev->mt76.mmio.wed_ext;
++
++	wed->wlan.pci_dev = pci_dev;
++	wed->wlan.bus_type = MTK_WED_BUS_PCIE;
++
++	wed->wlan.base = devm_ioremap(dev->mt76.dev,
++				      pci_resource_start(pci_dev, 0),
++				      pci_resource_len(pci_dev, 0));
++	wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
++
++	if (hif2) {
++		wed->wlan.wpdma_int = wed->wlan.phy_base +
++				      MT_INT_PCIE1_SOURCE_CSR_EXT;
++		wed->wlan.wpdma_mask = wed->wlan.phy_base +
++				       MT_INT_PCIE1_MASK_CSR;
++		wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
++					     MT_TXQ_RING_BASE(0) +
++					     MT7996_TXQ_BAND2 * MT_RING_SIZE;
++		if (dev->rro_support) {
++			wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
++						 MT_RXQ_RING_BASE(0) +
++						 MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
++			wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
++		} else {
++			wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
++						 MT_RXQ_RING_BASE(0) +
++						 MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
++			wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
++		}
++
++		wed->wlan.chip_id = 0x7991;
++		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
++	} else {
++		wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
++		wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
++		wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
++				     MT7996_TXQ_BAND0 * MT_RING_SIZE;
++
++		wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
++
++		wed->wlan.wpdma_rx = wed->wlan.phy_base +
++				     MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
++				     MT7996_RXQ_BAND0 * MT_RING_SIZE;
++
++		wed->wlan.rx_nbuf = 65536;
++		wed->wlan.rx_npkt = 24576;
++		wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
++
++		wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
++		wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
++
++		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
++		wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
++		if (dev->rro_support) {
++			wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
++						 MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
++			wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
++		} else {
++			wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
++			wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
++						  MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
++		}
++	}
++
++	wed->wlan.nbuf = 16384;
++
++	wed->wlan.token_start = 0;
++
++	wed->wlan.max_amsdu_nums = 8;
++	wed->wlan.max_amsdu_len = 1536;
++
++	wed->wlan.init_buf = mt7996_wed_init_buf;
++	wed->wlan.offload_enable = NULL;
++	wed->wlan.offload_disable = NULL;
++	wed->wlan.init_rx_buf = mt7996_mmio_wed_init_rx_buf;
++	wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
++	wed->wlan.update_wo_rx_stats = NULL;
++
++	dev->mt76.rx_token_size += wed->wlan.rx_npkt;
++
++	if (mtk_wed_device_attach(wed))
++		return 0;
++
++	*irq = wed->irq;
++	dev->mt76.dma_dev = wed->dev;
++
++	dev->mt76.token_size = 1024;
++
++	ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
++	if (ret)
++		return ret;
++
++	ret = dma_set_coherent_mask(wed->dev, DMA_BIT_MASK(32));
++	if (ret)
++		return ret;
++
++	return 1;
++#else
++	return 0;
++#endif
++}
++
+ static int mt7996_mmio_init(struct mt76_dev *mdev,
+ 			    void __iomem *mem_base,
+ 			    u32 device_id)
+@@ -241,8 +468,17 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
+ 	mdev->mmio.irqmask |= set;
+ 
+ 	if (write_reg) {
+-		mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
+-		mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
++		if (mtk_wed_device_active(&mdev->mmio.wed)) {
++			mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
++						    mdev->mmio.irqmask);
++			if (mtk_wed_device_active(&mdev->mmio.wed_ext)) {
++				mtk_wed_device_irq_set_mask(&mdev->mmio.wed_ext,
++							    mdev->mmio.irqmask);
++			}
++		} else {
++			mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
++			mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
++		}
+ 	}
+ 
+ 	spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
+@@ -260,22 +496,36 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
+ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ {
+ 	struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++	struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
+ 	u32 i, intr, mask, intr1;
+ 
+-	mt76_wr(dev, MT_INT_MASK_CSR, 0);
+-	if (dev->hif2)
+-		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+-
+-	intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
+-	intr &= dev->mt76.mmio.irqmask;
+-	mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+-
+-	if (dev->hif2) {
+-		intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
+-		intr1 &= dev->mt76.mmio.irqmask;
+-		mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
++	if (dev->hif2 && mtk_wed_device_active(wed_ext)) {
++		mtk_wed_device_irq_set_mask(wed_ext, 0);
++		intr1 = mtk_wed_device_irq_get(wed_ext,
++					       dev->mt76.mmio.irqmask);
++		if (intr1 & MT_INT_RX_TXFREE_EXT)
++			napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
++	}
+ 
+-		intr |= intr1;
++	if (mtk_wed_device_active(wed)) {
++		mtk_wed_device_irq_set_mask(wed, 0);
++		intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
++		intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
++	} else {
++		mt76_wr(dev, MT_INT_MASK_CSR, 0);
++		if (dev->hif2)
++			mt76_wr(dev, MT_INT1_MASK_CSR, 0);
++
++		intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
++		intr &= dev->mt76.mmio.irqmask;
++		mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
++		if (dev->hif2) {
++			intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
++			intr1 &= dev->mt76.mmio.irqmask;
++			mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
++			intr |= intr1;
++		}
+ 	}
+ 
+ 	trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
+@@ -307,10 +557,19 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
+ {
+ 	struct mt7996_dev *dev = dev_instance;
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ 
+-	mt76_wr(dev, MT_INT_MASK_CSR, 0);
+-	if (dev->hif2)
+-		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
++	if (mtk_wed_device_active(wed))
++		mtk_wed_device_irq_set_mask(wed, 0);
++	else
++		mt76_wr(dev, MT_INT_MASK_CSR, 0);
++
++	if (dev->hif2) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
++			mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_ext, 0);
++		else
++			mt76_wr(dev, MT_INT1_MASK_CSR, 0);
++	}
+ 
+ 	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
+ 		return IRQ_NONE;
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index e371964b..43f20da4 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -544,7 +544,9 @@ int mt7996_dma_init(struct mt7996_dev *dev);
+ void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+ void mt7996_dma_cleanup(struct mt7996_dev *dev);
+-void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset);
++int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
++			  int n_desc, int ring_base, struct mtk_wed_device *wed);
++void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset);
+ void mt7996_init_txpower(struct mt7996_dev *dev,
+ 			 struct ieee80211_supported_band *sband);
+ int mt7996_txbf_init(struct mt7996_dev *dev);
+@@ -732,7 +734,9 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
+ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 			    struct ieee80211_sta *sta, struct dentry *dir);
+ #endif
+-
++int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
++			 bool hif2, int *irq);
++u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+ #ifdef CONFIG_MTK_VENDOR
+ void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
+ void mt7996_vendor_register(struct mt7996_phy *phy);
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index c5301050..869f32ac 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -125,15 +125,26 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 	mt7996_wfsys_reset(dev);
+ 	hif2 = mt7996_pci_init_hif2(pdev);
+ 
+-	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++	ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
+ 	if (ret < 0)
+-		goto free_device;
++		goto free_wed_or_irq_vector;
+ 
+-	irq = pdev->irq;
+-	ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
++	if (!ret) {
++		ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++		if (ret < 0)
++			goto free_device;
++	}
++	ret = devm_request_irq(mdev->dev, pdev->irq, mt7996_irq_handler,
+ 			       IRQF_SHARED, KBUILD_MODNAME, dev);
+ 	if (ret)
+-		goto free_irq_vector;
++		goto free_wed_or_irq_vector;
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++		ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
++				       IRQF_SHARED, KBUILD_MODNAME "-wed", dev);
++		if (ret)
++			goto free_irq;
++	}
+ 
+ 	mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ 	/* master switch of PCIe tnterrupt enable */
+@@ -143,16 +154,30 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ 		hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
+ 		dev->hif2 = hif2;
+ 
+-		ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
++		ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &irq);
+ 		if (ret < 0)
+-			goto free_hif2;
++			goto free_irq;
++
++		if (!ret) {
++			ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
++			if (ret < 0)
++				goto free_hif2;
+ 
+-		dev->hif2->irq = hif2_dev->irq;
+-		ret = devm_request_irq(mdev->dev, dev->hif2->irq,
+-				       mt7996_irq_handler, IRQF_SHARED,
+-				       KBUILD_MODNAME "-hif", dev);
++			dev->hif2->irq = hif2_dev->irq;
++		}
++
++		ret = devm_request_irq(mdev->dev, hif2_dev->irq, mt7996_irq_handler,
++					IRQF_SHARED, KBUILD_MODNAME "-hif", dev);
+ 		if (ret)
+-			goto free_hif2_irq_vector;
++			goto free_hif2;
++
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
++			ret = devm_request_irq(mdev->dev, irq,
++					       mt7996_irq_handler, IRQF_SHARED,
++					       KBUILD_MODNAME "-wed-hif", dev);
++			if (ret)
++				goto free_hif2_irq_vector;
++		}
+ 
+ 		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ 		/* master switch of PCIe tnterrupt enable */
+@@ -168,15 +193,28 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
+ free_hif2_irq:
+ 	if (dev->hif2)
+ 		devm_free_irq(mdev->dev, dev->hif2->irq, dev);
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
++		devm_free_irq(mdev->dev, dev->mt76.mmio.wed_ext.irq, dev);
+ free_hif2_irq_vector:
+-	if (dev->hif2)
+-		pci_free_irq_vectors(hif2_dev);
++	if (dev->hif2) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
++			mtk_wed_device_detach(&dev->mt76.mmio.wed_ext);
++		else
++			pci_free_irq_vectors(hif2_dev);
++	}
+ free_hif2:
+ 	if (dev->hif2)
+ 		put_device(dev->hif2->dev);
+-	devm_free_irq(mdev->dev, irq, dev);
+-free_irq_vector:
+-	pci_free_irq_vectors(pdev);
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		devm_free_irq(mdev->dev, dev->mt76.mmio.wed.irq, dev);
++free_irq:
++	devm_free_irq(mdev->dev, pdev->irq, dev);
++free_wed_or_irq_vector:
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		mtk_wed_device_detach(&dev->mt76.mmio.wed);
++	else
++		pci_free_irq_vectors(pdev);
++
+ free_device:
+ 	mt76_free_device(&dev->mt76);
+ 
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 6ef905a9..04658639 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -323,6 +323,7 @@ enum base_rev {
+ 
+ #define MT_WFDMA0_RX_INT_PCIE_SEL		MT_WFDMA0(0x154)
+ #define MT_WFDMA0_RX_INT_SEL_RING3		BIT(3)
++#define MT_WFDMA0_RX_INT_SEL_RING6		BIT(6)
+ 
+ #define MT_WFDMA0_MCU_HOST_INT_ENA		MT_WFDMA0(0x1f4)
+ 
+@@ -367,6 +368,9 @@ enum base_rev {
+ #define MT_WFDMA0_PCIE1_BASE			0xd8000
+ #define MT_WFDMA0_PCIE1(ofs)			(MT_WFDMA0_PCIE1_BASE + (ofs))
+ 
++#define MT_INT_PCIE1_SOURCE_CSR_EXT 		MT_WFDMA0_PCIE1(0x118)
++#define MT_INT_PCIE1_MASK_CSR			MT_WFDMA0_PCIE1(0x11c)
++
+ #define MT_WFDMA0_PCIE1_BUSY_ENA		MT_WFDMA0_PCIE1(0x13c)
+ #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0	BIT(0)
+ #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1	BIT(1)
+@@ -412,6 +416,7 @@ enum base_rev {
+ #define MT_INT_RX_TXFREE_MAIN			BIT(17)
+ #define MT_INT_RX_TXFREE_TRI			BIT(15)
+ #define MT_INT_MCU_CMD				BIT(29)
++#define MT_INT_RX_TXFREE_EXT			BIT(26)
+ 
+ #define MT_INT_RX(q)				(dev->q_int_mask[__RXQ(q)])
+ #define MT_INT_TX_MCU(q)			(dev->q_int_mask[(q)])
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch
new file mode 100644
index 0000000..8452177
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch
@@ -0,0 +1,1465 @@
+From 0eaa67d2a2558d1366c25e18e43475907903dea4 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 13:50:56 +0800
+Subject: [PATCH 2004/2008] wifi: mt76: mt7996: wed: add wed3.0 rx support
+
+add hardware rro support, This is the preliminary patch for WED3.0 support.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Change-Id: I7e113b1392bcf085ec02c8a44ffbb7cf7c3fa027
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ dma.c           | 197 +++++++++++++++++++++++++++++++++++++-----------
+ dma.h           |  12 +++
+ mac80211.c      |   1 +
+ mt76.h          |  63 ++++++++++++++--
+ mt7996/dma.c    | 163 +++++++++++++++++++++++++++++++++------
+ mt7996/init.c   | 124 +++++++++++++++++++++++++++++-
+ mt7996/mac.c    |  42 +++++++++--
+ mt7996/mcu.c    |   8 +-
+ mt7996/mmio.c   |  36 +++++++--
+ mt7996/mt7996.h |  58 ++++++++++++++
+ mt7996/regs.h   |  63 +++++++++++++++-
+ 11 files changed, 675 insertions(+), 92 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index 930ec768..e5b4d898 100644
+--- a/dma.c
++++ b/dma.c
+@@ -193,46 +193,65 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
+ static void
+ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
+ {
++	int ndesc = q->ndesc;
++
++	if (q->flags & MT_QFLAG_MAGIC)
++		ndesc |= MT_DMA_MAGIC_EN;
++
+ 	Q_WRITE(dev, q, desc_base, q->desc_dma);
+-	Q_WRITE(dev, q, ring_size, q->ndesc);
++	Q_WRITE(dev, q, ring_size, ndesc);
+ 	q->head = Q_READ(dev, q, dma_idx);
+ 	q->tail = q->head;
+ }
+ 
+ static void
+-mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
++mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, bool skip)
+ {
+ 	int i;
+ 
+ 	if (!q || !q->ndesc)
+ 		return;
+ 
++	if (!q->desc)
++		goto done;
++
+ 	/* clear descriptors */
+ 	for (i = 0; i < q->ndesc; i++)
+ 		q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+ 
++	if (skip)
++		goto sync;
++
++done:
+ 	Q_WRITE(dev, q, cpu_idx, 0);
+ 	Q_WRITE(dev, q, dma_idx, 0);
++sync:
+ 	mt76_dma_sync_idx(dev, q);
+ }
+ 
+ static int
+ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+-		    struct mt76_queue_buf *buf, void *data)
++		    struct mt76_queue_buf *buf, void *data,
++		    struct mt76_rxwi_cache *rxwi)
+ {
+-	struct mt76_desc *desc = &q->desc[q->head];
++	struct mt76_desc *desc;
+ 	struct mt76_queue_entry *entry = &q->entry[q->head];
+-	struct mt76_rxwi_cache *rxwi = NULL;
+ 	u32 buf1 = 0, ctrl;
+ 	int idx = q->head;
+ 	int rx_token;
+ 
++	if (mt76_queue_is_rro_ind(q))
++		goto done;
++
++	desc = &q->desc[q->head];
+ 	ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+ 
+ 	if (mt76_queue_is_wed_rx(q)) {
+-		rxwi = mt76_get_rxwi(dev);
+-		if (!rxwi)
+-			return -ENOMEM;
++		if (!rxwi) {
++			rxwi = mt76_get_rxwi(dev);
++			if (!rxwi)
++				return -ENOMEM;
++		}
+ 
+ 		rx_token = mt76_rx_token_consume(dev, data, rxwi, buf->addr);
+ 		if (rx_token < 0) {
+@@ -249,6 +268,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+ 	WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
+ 	WRITE_ONCE(desc->info, 0);
+ 
++done:
+ 	entry->dma_addr[0] = buf->addr;
+ 	entry->dma_len[0] = buf->len;
+ 	entry->rxwi = rxwi;
+@@ -396,14 +416,15 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+ 
+ static void *
+ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+-		 int *len, u32 *info, bool *more, bool *drop)
++		 int *len, u32 *info, bool *more, bool *drop, bool flush)
+ {
+ 	struct mt76_queue_entry *e = &q->entry[idx];
+ 	struct mt76_desc *desc = &q->desc[idx];
+ 	void *buf;
++	u32 ctrl;
+ 
++	ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ 	if (len) {
+-		u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+ 		*len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
+ 		*more = !(ctrl & MT_DMA_CTL_LAST_SEC0);
+ 	}
+@@ -411,6 +432,12 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ 	if (info)
+ 		*info = le32_to_cpu(desc->info);
+ 
++	if (drop) {
++		*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
++		if (ctrl & MT_DMA_CTL_VER_MASK)
++			*drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
++	}
++
+ 	if (mt76_queue_is_wed_rx(q)) {
+ 		u32 buf1 = le32_to_cpu(desc->buf1);
+ 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
+@@ -423,20 +450,46 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ 				 SKB_WITH_OVERHEAD(q->buf_size),
+ 				 DMA_FROM_DEVICE);
+ 
+-		buf = r->ptr;
+-		r->dma_addr = 0;
+-		r->ptr = NULL;
+-
+-		mt76_put_rxwi(dev, r);
+-
+-		if (drop) {
+-			u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
+-
+-			*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
+-					   MT_DMA_CTL_DROP));
++		if (flush) {
++			buf = r->ptr;
++			r->dma_addr = 0;
++			r->ptr = NULL;
++
++			mt76_put_rxwi(dev, r);
++		} else {
++			struct mt76_queue_buf qbuf;
++
++			buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++			if (!buf)
++				return NULL;
++
++			memcpy(buf, r->ptr, SKB_WITH_OVERHEAD(q->buf_size));
++
++			r->dma_addr = dma_map_single(dev->dma_dev, r->ptr,
++						     SKB_WITH_OVERHEAD(q->buf_size),
++						     DMA_FROM_DEVICE);
++			if (unlikely(dma_mapping_error(dev->dma_dev, r->dma_addr))) {
++				skb_free_frag(r->ptr);
++				mt76_put_rxwi(dev, r);
++				return NULL;
++			}
++
++			qbuf.addr = r->dma_addr;
++			qbuf.len = SKB_WITH_OVERHEAD(q->buf_size);
++			qbuf.skip_unmap = false;
++
++			if (mt76_dma_add_rx_buf(dev, q, &qbuf, r->ptr, r) < 0) {
++				dma_unmap_single(dev->dma_dev, r->dma_addr,
++						 SKB_WITH_OVERHEAD(q->buf_size),
++						 DMA_FROM_DEVICE);
++				skb_free_frag(r->ptr);
++				mt76_put_rxwi(dev, r);
++				return NULL;
++			}
++		}
+ 
++		if (drop)
+ 			*drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
+-		}
+ 	} else {
+ 		buf = e->buf;
+ 		e->buf = NULL;
+@@ -458,15 +511,20 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+ 	if (!q->queued)
+ 		return NULL;
+ 
+-	if (flush)
+-		q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+-	else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
+-		return NULL;
++	if (q->flags & MT_QFLAG_RRO) {
++		goto done;
++	} else {
++		if (flush)
++			q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++		else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
++			return NULL;
++	}
+ 
++done:
+ 	q->tail = (q->tail + 1) % q->ndesc;
+ 	q->queued--;
+ 
+-	return mt76_dma_get_buf(dev, q, idx, len, info, more, drop);
++	return mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);
+ }
+ 
+ static int
+@@ -615,7 +673,10 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ 
+ 	while (q->queued < q->ndesc - 1) {
+ 		struct mt76_queue_buf qbuf;
+-		void *buf;
++		void *buf = NULL;
++
++		if (mt76_queue_is_rro_ind(q))
++			goto done;
+ 
+ 		buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
+ 		if (!buf)
+@@ -627,10 +688,11 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ 			break;
+ 		}
+ 
++done:
+ 		qbuf.addr = addr + offset;
+ 		qbuf.len = len - offset;
+ 		qbuf.skip_unmap = false;
+-		if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
++		if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf, NULL) < 0) {
+ 			dma_unmap_single(dev->dma_dev, addr, len,
+ 					 DMA_FROM_DEVICE);
+ 			skb_free_frag(buf);
+@@ -639,7 +701,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ 		frames++;
+ 	}
+ 
+-	if (frames)
++	if (frames || mt76_queue_is_wed_rx(q))
+ 		mt76_dma_kick_queue(dev, q);
+ 
+ 	spin_unlock_bh(&q->lock);
+@@ -652,7 +714,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ 	struct mtk_wed_device *wed = &dev->mmio.wed;
+ 	int ret, type, ring;
+-	u8 flags;
++	u16 flags;
+ 
+ 	if (!q || !q->ndesc)
+ 		return -EINVAL;
+@@ -679,7 +741,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ 	case MT76_WED_Q_TXFREE:
+ 		/* WED txfree queue needs ring to be initialized before setup */
+ 		q->flags = 0;
+-		mt76_dma_queue_reset(dev, q);
++		mt76_dma_queue_reset(dev, q, false);
+ 		mt76_dma_rx_fill(dev, q);
+ 		q->flags = flags;
+ 
+@@ -688,9 +750,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ 			q->wed_regs = wed->txfree_ring.reg_base;
+ 		break;
+ 	case MT76_WED_Q_RX:
+-		ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
+-		if (!ret)
+-			q->wed_regs = wed->rx_ring[ring].reg_base;
++		if (q->flags & MT_QFLAG_RRO) {
++			q->flags &= ~0x1f;
++
++			ring = FIELD_GET(MT_QFLAG_RRO_RING, q->flags);
++			type = FIELD_GET(MT_QFLAG_RRO_TYPE, q->flags);
++			if (type == MT76_RRO_Q_DATA) {
++				mt76_dma_queue_reset(dev, q, true);
++				ret = mtk_wed_device_rro_rx_ring_setup(wed, ring, q->regs);
++			} else if (type == MT76_RRO_Q_MSDU_PG) {
++				mt76_dma_queue_reset(dev, q, true);
++				ret = mtk_wed_device_msdu_pg_rx_ring_setup(wed, ring, q->regs);
++			} else if (type == MT76_RRO_Q_IND) {
++				mt76_dma_queue_reset(dev, q, false);
++				mt76_dma_rx_fill(dev, q);
++				ret = mtk_wed_device_ind_rx_ring_setup(wed, q->regs);
++			}
++			if (type != MT76_RRO_Q_IND) {
++				q->head = q->ndesc - 1;
++				q->queued = q->ndesc - 1;
++			}
++		} else {
++			ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, 0);
++			if (!ret)
++				q->wed_regs = wed->rx_ring[ring].reg_base;
++		}
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+@@ -719,10 +803,25 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ 	q->hw_idx = idx;
+ 
+ 	size = q->ndesc * sizeof(struct mt76_desc);
++	if (mt76_queue_is_rro_ind(q))
++		size = q->ndesc * sizeof(struct mt76_rro_desc);
++
+ 	q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
+ 	if (!q->desc)
+ 		return -ENOMEM;
+ 
++	if (mt76_queue_is_rro_ind(q)) {
++		struct mt76_rro_ind *cmd;
++		int i;
++
++		q->rro_desc = (struct mt76_rro_desc *)(q->desc);
++		q->desc = NULL;
++		for (i = 0; i < q->ndesc; i++) {
++			cmd = (struct mt76_rro_ind *) &q->rro_desc[i];
++			cmd->magic_cnt = MT_DMA_IND_CMD_MAGIC_CNT - 1;
++		}
++	}
++
+ 	size = q->ndesc * sizeof(*q->entry);
+ 	q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
+ 	if (!q->entry)
+@@ -732,8 +831,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ 	if (ret)
+ 		return ret;
+ 
+-	if (!mt76_queue_is_txfree(q))
+-		mt76_dma_queue_reset(dev, q);
++	if (!mtk_wed_device_active(&dev->mmio.wed) ||
++	    (!mt76_queue_is_wed_txfree(q) &&
++	     !(mtk_wed_get_rx_capa(&dev->mmio.wed) &&
++	       q->flags & MT_QFLAG_RRO)))
++		mt76_dma_queue_reset(dev, q, false);
+ 
+ 	return 0;
+ }
+@@ -751,13 +853,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+ 	spin_lock_bh(&q->lock);
+ 
+ 	do {
++		if (q->flags & MT_QFLAG_RRO)
++			break;
++
+ 		buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
+ 		if (!buf)
+ 			break;
+ 
+-		if (q->flags & MT_QFLAG_RRO)
+-			continue;
+-
+ 		skb_free_frag(buf);
+ 	} while (1);
+ 
+@@ -768,8 +870,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+ 
+ 	spin_unlock_bh(&q->lock);
+ 
+-	if (((q->flags & MT_QFLAG_WED) &&
+-	     FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) ||
++	if (mt76_queue_is_wed_rx(q) ||
+ 	    (q->flags & MT_QFLAG_RRO))
+ 		return;
+ 
+@@ -790,9 +891,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+ 	if (!q->ndesc)
+ 		return;
+ 
++	if (!q->desc)
++		goto done;
++
+ 	for (i = 0; i < q->ndesc; i++)
+ 		q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+ 
++done:
+ 	mt76_dma_rx_cleanup(dev, q);
+ 
+ 	/* reset WED rx queues */
+@@ -839,8 +944,8 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+ 	bool check_ddone = false;
+ 	bool more;
+ 
+-	if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
+-	    q->flags == MT_WED_Q_TXFREE) {
++	if ((IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
++	     q->flags == MT_WED_Q_TXFREE)) {
+ 		dma_idx = Q_READ(dev, q, dma_idx);
+ 		check_ddone = true;
+ 	}
+@@ -1002,7 +1107,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ 	mt76_for_each_q_rx(dev, i) {
+ 		struct mt76_queue *q = &dev->q_rx[i];
+ 
+-		if (mt76_queue_is_wed_rx(q))
++		if (mtk_wed_device_active(&dev->mmio.wed) &&
++		    (q->flags & MT_QFLAG_RRO))
+ 			continue;
+ 
+ 		netif_napi_del(&dev->napi[i]);
+@@ -1014,6 +1120,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+ 
+ 	if (mtk_wed_device_active(&dev->mmio.wed_ext))
+ 		mtk_wed_device_detach(&dev->mmio.wed_ext);
++
+ 	mt76_free_pending_txwi(dev);
+ 	mt76_free_pending_rxwi(dev);
+ }
+diff --git a/dma.h b/dma.h
+index 1b090d78..48037092 100644
+--- a/dma.h
++++ b/dma.h
+@@ -25,6 +25,13 @@
+ #define MT_DMA_PPE_ENTRY		GENMASK(30, 16)
+ #define MT_DMA_INFO_PPE_VLD		BIT(31)
+ 
++#define MT_DMA_CTL_PN_CHK_FAIL		BIT(13)
++#define MT_DMA_CTL_VER_MASK		BIT(7)
++
++#define MT_DMA_MAGIC_EN		BIT(13)
++
++#define MT_DMA_IND_CMD_MAGIC_CNT	8
++
+ #define MT_DMA_HDR_LEN			4
+ #define MT_RX_INFO_LEN			4
+ #define MT_FCE_INFO_LEN			4
+@@ -37,6 +44,11 @@ struct mt76_desc {
+ 	__le32 info;
+ } __packed __aligned(4);
+ 
++struct mt76_rro_desc {
++	__le32 buf0;
++	__le32 buf1;
++} __packed __aligned(4);
++
+ enum mt76_qsel {
+ 	MT_QSEL_MGMT,
+ 	MT_QSEL_HCCA,
+diff --git a/mac80211.c b/mac80211.c
+index f7578308..3a5755f9 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -727,6 +727,7 @@ static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
+ 			return;
+ 		}
+ 	}
++
+ 	__skb_queue_tail(&dev->rx_skb[q], skb);
+ }
+ 
+diff --git a/mt76.h b/mt76.h
+index ee0dbdd7..e4351338 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -48,6 +48,18 @@
+ 
+ #define MT76_TOKEN_FREE_THR	64
+ 
++#define MT_QFLAG_RRO_RING	GENMASK(6, 5)
++#define MT_QFLAG_RRO_TYPE	GENMASK(8, 7)
++#define MT_QFLAG_RRO		BIT(9)
++#define MT_QFLAG_MAGIC		BIT(10)
++
++#define __MT_RRO_Q(_type, _n)	(MT_QFLAG_RRO | \
++				 FIELD_PREP(MT_QFLAG_RRO_TYPE, _type) | \
++				 FIELD_PREP(MT_QFLAG_RRO_RING, _n))
++#define MT_RRO_Q_DATA(_n)	__MT_RRO_Q(MT76_RRO_Q_DATA, _n)
++#define MT_RRO_Q_MSDU_PG(_n)	__MT_RRO_Q(MT76_RRO_Q_MSDU_PG, _n)
++#define MT_RRO_Q_IND		__MT_RRO_Q(MT76_RRO_Q_IND, 0)
++
+ #define MT_QFLAG_WED_RING	GENMASK(1, 0)
+ #define MT_QFLAG_WED_TYPE	GENMASK(3, 2)
+ #define MT_QFLAG_WED		BIT(4)
+@@ -82,6 +94,12 @@ enum mt76_wed_type {
+ 	MT76_WED_Q_RX,
+ };
+ 
++enum mt76_RRO_type {
++	MT76_RRO_Q_DATA,
++	MT76_RRO_Q_MSDU_PG,
++	MT76_RRO_Q_IND,
++};
++
+ struct mt76_bus_ops {
+ 	u32 (*rr)(struct mt76_dev *dev, u32 offset);
+ 	void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
+@@ -128,6 +146,16 @@ enum mt76_rxq_id {
+ 	MT_RXQ_MAIN_WA,
+ 	MT_RXQ_BAND2,
+ 	MT_RXQ_BAND2_WA,
++	MT_RXQ_RRO_BAND0,
++	MT_RXQ_RRO_BAND1,
++	MT_RXQ_RRO_BAND2,
++	MT_RXQ_MSDU_PAGE_BAND0,
++	MT_RXQ_MSDU_PAGE_BAND1,
++	MT_RXQ_MSDU_PAGE_BAND2,
++	MT_RXQ_TXFREE_BAND0,
++	MT_RXQ_TXFREE_BAND1,
++	MT_RXQ_TXFREE_BAND2,
++	MT_RXQ_RRO_IND,
+ 	__MT_RXQ_MAX
+ };
+ 
+@@ -206,6 +234,7 @@ struct mt76_queue {
+ 	spinlock_t lock;
+ 	spinlock_t cleanup_lock;
+ 	struct mt76_queue_entry *entry;
++	struct mt76_rro_desc *rro_desc;
+ 	struct mt76_desc *desc;
+ 
+ 	u16 first;
+@@ -219,8 +248,8 @@ struct mt76_queue {
+ 
+ 	u8 buf_offset;
+ 	u8 hw_idx;
+-	u8 flags;
+-
++	u8 magic_cnt;
++	u32 flags;
+ 	u32 wed_regs;
+ 
+ 	dma_addr_t desc_dma;
+@@ -274,7 +303,7 @@ struct mt76_queue_ops {
+ 
+ 	void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
+ 
+-	void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
++	void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q, bool skip);
+ };
+ 
+ enum mt76_phy_type {
+@@ -369,6 +398,17 @@ struct mt76_txq {
+ 	bool aggr;
+ };
+ 
++struct mt76_rro_ind {
++	u32 se_id	: 12;
++	u32 rsv		: 4;
++	u32 start_sn	: 12;
++	u32 ind_reason	: 4;
++	u32 ind_cnt	: 13;
++	u32 win_sz	: 3;
++	u32 rsv2	: 13;
++	u32 magic_cnt	: 3;
++};
++
+ struct mt76_txwi_cache {
+ 	struct list_head list;
+ 	dma_addr_t dma_addr;
+@@ -1516,12 +1556,19 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
+ 	return (q->flags & MT_QFLAG_WED) &&
+ 	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
+ }
+-static inline bool mt76_queue_is_txfree(struct mt76_queue *q)
++
++static inline bool mt76_queue_is_wed_txfree(struct mt76_queue *q)
+ {
+ 	return (q->flags & MT_QFLAG_WED) &&
+ 	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
+ }
+ 
++static inline bool mt76_queue_is_rro_ind(struct mt76_queue *q)
++{
++	return (q->flags & MT_QFLAG_RRO) &&
++	       FIELD_GET(MT_QFLAG_RRO_TYPE, q->flags) == MT76_RRO_Q_IND;
++}
++
+ struct mt76_txwi_cache *
+ mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
+ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
+@@ -1540,10 +1587,14 @@ static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
+ static inline int
+ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
+ {
+-	int token;
++	int token, start = 0;
++
++	if (mtk_wed_device_active(&dev->mmio.wed))
++		start = dev->mmio.wed.wlan.nbuf;
+ 
+ 	spin_lock_bh(&dev->token_lock);
+-	token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
++	token = idr_alloc(&dev->token, *ptxwi, start, start + dev->token_size,
++			  GFP_ATOMIC);
+ 	spin_unlock_bh(&dev->token_lock);
+ 
+ 	return token;
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index 673b08bb..c5c7f160 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -64,6 +64,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
+ 	RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
+ 	RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
+ 
++	if (dev->rro_support) {
++		/* band0 */
++		RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
++			   MT7996_RXQ_RRO_BAND0);
++		RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
++			   MT7996_RXQ_MSDU_PG_BAND0);
++		RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
++			   MT7996_RXQ_TXFREE0);
++		/* band1 */
++		RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
++			   MT7996_RXQ_MSDU_PG_BAND1);
++		/* band2 */
++		RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
++			   MT7996_RXQ_RRO_BAND2);
++		RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
++			   MT7996_RXQ_MSDU_PG_BAND2);
++		RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
++			   MT7996_RXQ_TXFREE2);
++
++		RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
++			   MT7996_RXQ_RRO_IND);
++	}
++
+ 	/* data tx queue */
+ 	TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
+ 	TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
+@@ -91,6 +114,22 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
+ 	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x180, 0x2));
+ 	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10));
+ 	mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10));
++	if (dev->rro_support) {
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
++			PREFETCH(0x3a0, 0x10));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
++			PREFETCH(0x4a0, 0x10));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
++			PREFETCH(0x5a0, 0x4));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
++			PREFETCH(0x5e0, 0x4));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
++			PREFETCH(0x620, 0x4));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
++			PREFETCH(0x660, 0x2));
++		mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
++			PREFETCH(0x680, 0x2));
++	}
+ 
+ 	mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
+ }
+@@ -149,6 +188,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
+ 
+ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ {
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ 	u32 hif1_ofs = 0;
+ 	u32 irq_mask;
+ 
+@@ -157,11 +197,16 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ 
+ 	/* enable wpdma tx/rx */
+ 	if (!reset) {
+-		mt76_set(dev, MT_WFDMA0_GLO_CFG,
+-			 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-			 MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+-			 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+-			 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++		if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
++			mt76_set(dev, MT_WFDMA0_GLO_CFG,
++				 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++				 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO);
++		else
++			mt76_set(dev, MT_WFDMA0_GLO_CFG,
++				MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++				MT_WFDMA0_GLO_CFG_RX_DMA_EN |
++				MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++				MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+ 
+ 		if (dev->hif2)
+ 			mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+@@ -173,8 +218,8 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ 
+ 	/* enable interrupts for TX/RX rings */
+ 	irq_mask = MT_INT_MCU_CMD |
+-			   MT_INT_RX_DONE_MCU |
+-			   MT_INT_TX_DONE_MCU;
++		   MT_INT_RX_DONE_MCU |
++		   MT_INT_TX_DONE_MCU;
+ 
+ 	if (mt7996_band_valid(dev, MT_BAND0))
+ 		irq_mask |= MT_INT_BAND0_RX_DONE;
+@@ -185,14 +230,14 @@ void __mt7996_dma_enable(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ 	if (mt7996_band_valid(dev, MT_BAND2))
+ 		irq_mask |= MT_INT_BAND2_RX_DONE;
+ 
+-	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) {
++	if (mtk_wed_device_active(wed) && wed_reset) {
+ 		u32 wed_irq_mask = irq_mask;
+ 
+ 		wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
+ 
+ 		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
+ 
+-		mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
++		mtk_wed_device_start(wed, wed_irq_mask);
+ 	}
+ 
+ 	irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
+@@ -269,7 +314,8 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 		/* fix hardware limitation, pcie1's rx ring3 is not available
+ 		 * so, redirect pcie0 rx ring3 interrupt to pcie1
+ 		 */
+-		if (mtk_wed_device_active(&dev->mt76.mmio.wed) && dev->rro_support)
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    dev->rro_support)
+ 			mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
+ 				 MT_WFDMA0_RX_INT_SEL_RING6);
+ 		else
+@@ -282,6 +328,78 @@ static int mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
+ 	return 0;
+ }
+ 
++int mt7996_dma_rro_init(struct mt7996_dev *dev)
++{
++	int ret;
++	u32 hif1_ofs = 0;
++	u32 wed_irq_mask;
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++
++	if (dev->hif2)
++		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++
++	/* ind cmd */
++	dev->mt76.q_rx[MT_RXQ_RRO_IND].flags = MT_RRO_Q_IND | MT_WED_Q_RX(0);
++	dev->mt76.q_rx[MT_RXQ_RRO_IND].flags |= MT_WED_Q_RX(0);
++	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_IND],
++			       MT_RXQ_ID(MT_RXQ_RRO_IND),
++			       MT7996_RX_RING_SIZE,
++			       0, MT_RXQ_RRO_IND_RING_BASE);
++	if (ret)
++		return ret;
++
++	/* rx msdu page queue for band0 */
++	dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags = MT_RRO_Q_MSDU_PG(0);
++	dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags |= MT_QFLAG_MAGIC;
++	dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags |= MT_WED_Q_RX(0);
++	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0],
++			       MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
++			       MT7996_RX_RING_SIZE,
++			       MT7996_RX_MSDU_PAGE_SIZE,
++			       MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
++	if (ret)
++		return ret;
++
++	if (mt7996_band_valid(dev, MT_BAND1)) {
++		/* rx msdu page queue for band1 */
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags = MT_RRO_Q_MSDU_PG(1);
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags |= MT_QFLAG_MAGIC;
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags |= MT_WED_Q_RX(1);
++		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1],
++				       MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
++				       MT7996_RX_RING_SIZE,
++				       MT7996_RX_MSDU_PAGE_SIZE,
++				       MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
++		if (ret)
++			return ret;
++	}
++
++	if (mt7996_band_valid(dev, MT_BAND2)) {
++		/* rx msdu page queue for band2 */
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags = MT_RRO_Q_MSDU_PG(2);
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags |= MT_QFLAG_MAGIC;
++		dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags |= MT_WED_Q_RX(0);
++		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2],
++				       MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
++				       MT7996_RX_RING_SIZE,
++				       MT7996_RX_MSDU_PAGE_SIZE,
++				       MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
++		if (ret)
++			return ret;
++	}
++
++	wed_irq_mask = dev->mt76.mmio.irqmask |
++		       MT_INT_RRO_RX_DONE |
++		       MT_INT_TX_DONE_BAND2;
++
++	mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
++
++	mtk_wed_device_start_hwrro(wed, wed_irq_mask, false);
++	mt7996_irq_enable(dev, wed_irq_mask);
++
++	return 0;
++}
++
+ int mt7996_dma_init(struct mt7996_dev *dev)
+ {
+ 	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+@@ -351,6 +469,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 		return ret;
+ 
+ 	/* rx data queue for band0 and band1 */
++	if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
++		dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0);
++
+ 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
+ 			       MT_RXQ_ID(MT_RXQ_MAIN),
+ 			       MT7996_RX_RING_SIZE,
+@@ -374,9 +495,6 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	if (mt7996_band_valid(dev, MT_BAND2)) {
+ 		/* rx data queue for band2 */
+ 		rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
+-		if (mtk_wed_device_active(wed))
+-			rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
+-
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ 				       MT_RXQ_ID(MT_RXQ_BAND2),
+ 				       MT7996_RX_RING_SIZE,
+@@ -400,11 +518,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 			return ret;
+ 	}
+ 
+-
+-	if (dev->rro_support) {
++	if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
++	    dev->rro_support) {
+ 		/* rx rro data queue for band0 */
+ 		dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags = MT_RRO_Q_DATA(0);
+ 		dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_QFLAG_MAGIC;
++		dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags |= MT_WED_Q_RX(0);
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
+ 				       MT_RXQ_ID(MT_RXQ_RRO_BAND0),
+ 				       MT7996_RX_RING_SIZE,
+@@ -414,8 +533,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 			return ret;
+ 
+ 		/* tx free notify event from WA for band0 */
+-		if (mtk_wed_device_active(wed))
+-			dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
++		dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
+ 				       MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
+ 				       MT7996_RX_MCU_RING_SIZE,
+@@ -428,6 +546,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 			/* rx rro data queue for band2 */
+ 			dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags = MT_RRO_Q_DATA(1);
+ 			dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_QFLAG_MAGIC;
++			dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags |= MT_WED_Q_RX(1);
+ 			ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
+ 					       MT_RXQ_ID(MT_RXQ_RRO_BAND2),
+ 					       MT7996_RX_RING_SIZE,
+@@ -505,18 +624,18 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+ 
+ 	/* reset hw queues */
+ 	for (i = 0; i < __MT_TXQ_MAX; i++) {
+-		mt76_queue_reset(dev, dev->mphy.q_tx[i]);
++		mt76_queue_reset(dev, dev->mphy.q_tx[i], false);
+ 		if (phy2)
+-			mt76_queue_reset(dev, phy2->q_tx[i]);
++			mt76_queue_reset(dev, phy2->q_tx[i], false);
+ 		if (phy3)
+-			mt76_queue_reset(dev, phy3->q_tx[i]);
++			mt76_queue_reset(dev, phy3->q_tx[i], false);
+ 	}
+ 
+ 	for (i = 0; i < __MT_MCUQ_MAX; i++)
+-		mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
++		mt76_queue_reset(dev, dev->mt76.q_mcu[i], false);
+ 
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
+-		mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
++		mt76_queue_reset(dev, &dev->mt76.q_rx[i], false);
+ 	}
+ 
+ 	mt76_tx_status_check(&dev->mt76, true);
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 6cfbc50d..d70dcf9f 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -496,8 +496,13 @@ void mt7996_mac_init(struct mt7996_dev *dev)
+ 
+ 	/* rro module init */
+ 	mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
+-	mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
+-	mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
++	if (dev->rro_support) {
++		mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
++		mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
++	} else {
++		mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
++		mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
++	}
+ 
+ 	mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+ 			  MCU_WA_PARAM_HW_PATH_HIF_VER,
+@@ -650,6 +655,114 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
+ 	msleep(20);
+ }
+ 
++static int mt7996_rro_init(struct mt7996_dev *dev)
++{
++	struct mt7996_rro_addr *ptr;
++	struct mt7996_rro_cfg *rro = &dev->rro;
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++	u32 size, val = 0, reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
++	int i, j;
++	void *buf;
++
++	for (i = 0; i < MT7996_RRO_BA_BITMAP_CR_CNT; i++) {
++		buf = dmam_alloc_coherent(dev->mt76.dma_dev,
++					  MT7996_BA_BITMAP_SZ_PER_CR,
++					  &rro->ba_bitmap_cache_pa[i],
++					  GFP_KERNEL);
++		if (!buf)
++			return -ENOMEM;
++
++		rro->ba_bitmap_cache_va[i] = buf;
++	}
++
++	rro->win_sz = MT7996_RRO_WIN_SIZE_MAX;
++	for (i = 0; i < MT7996_RRO_ADDR_ELEM_CR_CNT; i++) {
++		size = MT7996_RRO_SESSION_PER_CR *
++		       rro->win_sz * sizeof(struct mt7996_rro_addr);
++
++		buf = dmam_alloc_coherent(dev->mt76.dma_dev, size,
++					  &rro->addr_elem_alloc_pa[i],
++					  GFP_KERNEL);
++		if (!buf)
++			return -ENOMEM;
++		rro->addr_elem_alloc_va[i] = buf;
++
++		memset(rro->addr_elem_alloc_va[i], 0, size);
++
++		ptr = rro->addr_elem_alloc_va[i];
++		for (j = 0; j < MT7996_RRO_SESSION_PER_CR * rro->win_sz; j++, ptr++)
++			ptr->signature = 0xff;
++
++		wed->wlan.ind_cmd.addr_elem_phys[i] = rro->addr_elem_alloc_pa[i];
++	}
++
++	rro->particular_se_id = MT7996_RRO_SESSION_MAX;
++	size = rro->win_sz * sizeof(struct mt7996_rro_addr);
++	buf = dmam_alloc_coherent(dev->mt76.dma_dev, size,
++				  &rro->particular_session_pa,
++				  GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	rro->particular_session_va = buf;
++	ptr = rro->particular_session_va;
++	for (j = 0; j < rro->win_sz; j++, ptr++)
++		ptr->signature = 0xff;
++
++	INIT_LIST_HEAD(&rro->pg_addr_cache);
++	for (i = 0; i < MT7996_RRO_MSDU_PG_HASH_SIZE; i++)
++		INIT_LIST_HEAD(&rro->pg_hash_head[i]);
++
++	/* rro hw init */
++	/* TODO: remove line after WM has set */
++	mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
++
++	/* setup BA bitmap cache address */
++	mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
++		rro->ba_bitmap_cache_pa[0]);
++	mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
++	mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
++		rro->ba_bitmap_cache_pa[1]);
++	mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
++
++	/* setup Address element address */
++	for (i = 0; i < MT7996_RRO_ADDR_ELEM_CR_CNT; i++) {
++		mt76_wr(dev, reg, rro->addr_elem_alloc_pa[i] >> 4);
++		reg += 4;
++	}
++
++	/* setup Address element address - separate address segment mode */
++	mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
++		MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
++
++	wed->wlan.ind_cmd.win_size = ffs(rro->win_sz) - 6;
++	wed->wlan.ind_cmd.particular_sid = rro->particular_se_id;
++	wed->wlan.ind_cmd.particular_se_phys = rro->particular_session_pa;
++	wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_CR_CNT;
++	wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
++
++	mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
++	mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
++		 MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
++
++	/* particular session configure */
++	/* use max session idx + 1 as particular session id */
++	mt76_wr(dev, MT_RRO_PARTICULAR_CFG0,
++		rro->particular_session_pa);
++
++	val = FIELD_PREP(MT_RRO_PARTICULAR_SID,
++			 MT7996_RRO_SESSION_MAX);
++	val |= MT_RRO_PARTICULAR_CONFG_EN;
++	mt76_wr(dev, MT_RRO_PARTICULAR_CFG1, val);
++
++	/* interrupt enable */
++	mt76_wr(dev, MT_RRO_HOST_INT_ENA,
++		MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
++
++	/* rro ind cmd queue init */
++	return mt7996_dma_rro_init(dev);
++}
++
+ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ {
+ 	int ret, idx;
+@@ -677,6 +790,13 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++	    dev->rro_support) {
++		ret = mt7996_rro_init(dev);
++		if (ret)
++			return ret;
++	}
++
+ 	ret = mt7996_eeprom_init(dev);
+ 	if (ret < 0)
+ 		return ret;
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index fc2d9269..4fbbc077 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -614,8 +614,37 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
+ 	return 0;
+ }
+ 
++static void
++mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
++		     struct mt7996_sta *msta, struct sk_buff *skb,
++		     u32 info)
++{
++	struct ieee80211_vif *vif;
++	struct wireless_dev *wdev;
++
++	if (!msta || !msta->vif)
++		return;
++
++	if (!mt76_queue_is_wed_rx(q))
++		return;
++
++	if (!(info & MT_DMA_INFO_PPE_VLD))
++		return;
++
++	vif = container_of((void *)msta->vif, struct ieee80211_vif,
++			   drv_priv);
++	wdev = ieee80211_vif_to_wdev(vif);
++	skb->dev = wdev->netdev;
++
++	mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
++				 FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
++				 FIELD_GET(MT_DMA_PPE_ENTRY, info));
++}
++
++
+ static int
+-mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
++mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
++		   struct sk_buff *skb, u32 *info)
+ {
+ 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ 	struct mt76_phy *mphy = &dev->mt76.phy;
+@@ -640,7 +669,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	u16 seq_ctrl = 0;
+ 	__le16 fc = 0;
+ 	int idx;
++	u8 hw_aggr = false;
++	struct mt7996_sta *msta = NULL;
+ 
++	hw_aggr = status->aggr;
+ 	memset(status, 0, sizeof(*status));
+ 
+ 	band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
+@@ -667,8 +699,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
+ 
+ 	if (status->wcid) {
+-		struct mt7996_sta *msta;
+-
+ 		msta = container_of(status->wcid, struct mt7996_sta, wcid);
+ 		spin_lock_bh(&dev->sta_poll_lock);
+ 		if (list_empty(&msta->poll_list))
+@@ -871,12 +901,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+ #endif
+ 	} else {
+ 		status->flag |= RX_FLAG_8023;
++		mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
++				     *info);
+ 	}
+ 
+ 	if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
+ 		mt7996_mac_decode_he_radiotap(skb, rxv, mode);
+ 
+-	if (!status->wcid || !ieee80211_is_data_qos(fc))
++	if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
+ 		return 0;
+ 
+ 	status->aggr = unicast &&
+@@ -1604,7 +1636,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 		dev_kfree_skb(skb);
+ 		break;
+ 	case PKT_TYPE_NORMAL:
+-		if (!mt7996_mac_fill_rx(dev, skb)) {
++		if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
+ 			mt76_rx(&dev->mt76, q, skb);
+ 			return;
+ 		}
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 59f22f6d..1891c0d7 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -949,7 +949,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
+ static int
+ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ 		  struct ieee80211_ampdu_params *params,
+-		  bool enable, bool tx)
++		  bool enable, bool tx, bool rro_enable)
+ {
+ 	struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
+ 	struct sta_rec_ba_uni *ba;
+@@ -970,6 +970,8 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
+ 	ba->ba_en = enable << params->tid;
+ 	ba->amsdu = params->amsdu;
+ 	ba->tid = params->tid;
++	if (rro_enable && !tx && enable)
++		ba->ba_rdd_rro = true;
+ 
+ 	return mt76_mcu_skb_send_msg(dev, skb,
+ 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+@@ -987,7 +989,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
+ 		msta->wcid.amsdu = false;
+ 
+ 	return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+-				 enable, true);
++				 enable, true, dev->rro_support);
+ }
+ 
+ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+@@ -998,7 +1000,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
+ 	struct mt7996_vif *mvif = msta->vif;
+ 
+ 	return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+-				 enable, false);
++				 enable, false, dev->rro_support);
+ }
+ 
+ static void
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index b9e47e73..9960dca7 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -346,9 +346,15 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 			wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
+ 		}
+ 
++		wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
++		wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
++				     MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
++				     MT7996_RXQ_BAND0 * MT_RING_SIZE;
++
+ 		wed->wlan.chip_id = 0x7991;
+ 		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
+ 	} else {
++		wed->wlan.hwrro = dev->rro_support; /* default on */
+ 		wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
+ 		wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
+ 		wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
+@@ -360,13 +366,33 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 				     MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
+ 				     MT7996_RXQ_BAND0 * MT_RING_SIZE;
+ 
++		wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
++					    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
++					    MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
++		wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
++					    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
++					    MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
++		wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
++					MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
++					MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
++
+ 		wed->wlan.rx_nbuf = 65536;
+ 		wed->wlan.rx_npkt = 24576;
++		if (dev->hif2)
++			wed->wlan.rx_npkt += 8192;
++
+ 		wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
+ 
+ 		wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
+ 		wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
+ 
++		wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
++		wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
++
++		wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
++		wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
++		wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
++
+ 		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
+ 		wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
+ 		if (dev->rro_support) {
+@@ -378,6 +404,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 			wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
+ 						  MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
+ 		}
++
++		dev->mt76.rx_token_size += wed->wlan.rx_npkt;
+ 	}
+ 
+ 	wed->wlan.nbuf = 16384;
+@@ -394,8 +422,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 	wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
+ 	wed->wlan.update_wo_rx_stats = NULL;
+ 
+-	dev->mt76.rx_token_size += wed->wlan.rx_npkt;
+-
+ 	if (mtk_wed_device_attach(wed))
+ 		return 0;
+ 
+@@ -557,10 +583,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
+ {
+ 	struct mt7996_dev *dev = dev_instance;
+-	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ 
+-	if (mtk_wed_device_active(wed))
+-		mtk_wed_device_irq_set_mask(wed, 0);
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
+ 	else
+ 		mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ 
+@@ -592,6 +617,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
+ 				SURVEY_INFO_TIME_RX |
+ 				SURVEY_INFO_TIME_BSS_RX,
+ 		.token_size = MT7996_TOKEN_SIZE,
++		.rx_token_size = MT7996_RX_TOKEN_SIZE,
+ 		.tx_prepare_skb = mt7996_tx_prepare_skb,
+ 		.tx_complete_skb = mt76_connac_tx_complete_skb,
+ 		.rx_skb = mt7996_queue_rx_skb,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 43f20da4..836c7db7 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -39,6 +39,7 @@
+ #define MT7996_EEPROM_SIZE		7680
+ #define MT7996_EEPROM_BLOCK_SIZE	16
+ #define MT7996_TOKEN_SIZE		16384
++#define MT7996_RX_TOKEN_SIZE		16384
+ 
+ #define MT7996_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */
+ #define MT7996_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
+@@ -63,6 +64,24 @@
+ #define MT7996_SKU_RATE_NUM		417
+ #define MT7996_SKU_PATH_NUM		494
+ 
++#define MT7996_RRO_MSDU_PG_HASH_SIZE	127
++#define MT7996_RRO_SESSION_MAX		1024
++#define MT7996_RRO_WIN_SIZE_MAX		1024
++#define MT7996_RRO_ADDR_ELEM_CR_CNT	128
++#define MT7996_RRO_BA_BITMAP_CR_CNT	2
++#define MT7996_RRO_SESSION_PER_CR	(MT7996_RRO_SESSION_MAX /	\
++					 MT7996_RRO_ADDR_ELEM_CR_CNT)
++#define MT7996_BA_BITMAP_SZ_PER_SESSION	128
++#define MT7996_BA_BITMAP_SZ_PER_CR	((MT7996_RRO_SESSION_MAX *		\
++					 MT7996_BA_BITMAP_SZ_PER_SESSION) /	\
++					 MT7996_RRO_BA_BITMAP_CR_CNT)
++#define MT7996_SKB_TRUESIZE(x)		((x) +	\
++					 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
++#define MT7996_RX_BUF_SIZE		MT7996_SKB_TRUESIZE(1800)
++#define MT7996_RX_MSDU_PAGE_SIZE	MT7996_SKB_TRUESIZE(128)
++
++#define MT7996_WED_RX_TOKEN_SIZE	32768
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -102,6 +121,16 @@ enum mt7996_rxq_id {
+ 	MT7996_RXQ_BAND0 = 4,
+ 	MT7996_RXQ_BAND1 = 4,/* unused */
+ 	MT7996_RXQ_BAND2 = 5,
++	MT7996_RXQ_RRO_BAND0 = 8,
++	MT7996_RXQ_RRO_BAND1 = 8,/* unused */
++	MT7996_RXQ_RRO_BAND2 = 6,
++	MT7996_RXQ_MSDU_PG_BAND0 = 10,
++	MT7996_RXQ_MSDU_PG_BAND1 = 11,
++	MT7996_RXQ_MSDU_PG_BAND2 = 12,
++	MT7996_RXQ_TXFREE0 = 9,
++	MT7996_RXQ_TXFREE1 = 9,
++	MT7996_RXQ_TXFREE2 = 7,
++	MT7996_RXQ_RRO_IND = 0,
+ };
+ 
+ struct mt7996_twt_flow {
+@@ -272,6 +301,31 @@ struct mt7996_air_monitor_ctrl {
+ };
+ #endif
+ 
++struct mt7996_rro_addr {
++	u32 head_pkt_l;
++	u32 head_pkt_h	: 4;
++	u32 seg_cnt	: 11;
++	u32 out_of_range: 1;
++	u32 rsv		: 8;
++	u32 signature	: 8;
++};
++
++struct mt7996_rro_cfg {
++	u32 ind_signature;
++	void *ba_bitmap_cache_va[MT7996_RRO_BA_BITMAP_CR_CNT];
++	void *addr_elem_alloc_va[MT7996_RRO_ADDR_ELEM_CR_CNT];
++	void *particular_session_va;
++	u32 particular_se_id;
++	dma_addr_t ba_bitmap_cache_pa[MT7996_RRO_BA_BITMAP_CR_CNT];
++	dma_addr_t addr_elem_alloc_pa[MT7996_RRO_ADDR_ELEM_CR_CNT];
++	dma_addr_t particular_session_pa;
++	u16 win_sz;
++
++	spinlock_t lock;
++	struct list_head pg_addr_cache;
++	struct list_head pg_hash_head[MT7996_RRO_MSDU_PG_HASH_SIZE];
++};
++
+ struct mt7996_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -390,6 +444,9 @@ struct mt7996_dev {
+ 	bool flash_mode:1;
+ 	bool has_eht:1;
+ 
++	bool rro_support:1;
++	struct mt7996_rro_cfg rro;
++
+ 	bool testmode_enable;
+ 	bool bin_file_mode;
+ 	u8 eeprom_mode;
+@@ -709,6 +766,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 			  struct ieee80211_sta *sta,
+ 			  struct mt76_tx_info *tx_info);
+ void mt7996_tx_token_put(struct mt7996_dev *dev);
++int mt7996_dma_rro_init(struct mt7996_dev *dev);
+ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 			 struct sk_buff *skb, u32 *info);
+ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 04658639..6624685e 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -39,6 +39,40 @@ enum base_rev {
+ 
+ #define __BASE(_id, _band)			(dev->reg.base[(_id)].band_base[(_band)])
+ 
++
++/* RRO TOP */
++#define MT_RRO_TOP_BASE				0xA000
++#define MT_RRO_TOP(ofs)				(MT_RRO_TOP_BASE + (ofs))
++
++#define MT_RRO_BA_BITMAP_BASE0			MT_RRO_TOP(0x8)
++#define MT_RRO_BA_BITMAP_BASE1			MT_RRO_TOP(0xC)
++#define WF_RRO_AXI_MST_CFG			MT_RRO_TOP(0xB8)
++#define WF_RRO_AXI_MST_CFG_DIDX_OK		BIT(12)
++#define MT_RRO_ADDR_ARRAY_BASE1			MT_RRO_TOP(0x34)
++#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE	BIT(31)
++
++#define MT_RRO_IND_CMD_SIGNATURE_BASE0		MT_RRO_TOP(0x38)
++#define MT_RRO_IND_CMD_SIGNATURE_BASE1		MT_RRO_TOP(0x3C)
++#define MT_RRO_IND_CMD_0_CTRL0			MT_RRO_TOP(0x40)
++#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN	BIT(31)
++
++#define MT_RRO_PARTICULAR_CFG0			MT_RRO_TOP(0x5C)
++#define MT_RRO_PARTICULAR_CFG1			MT_RRO_TOP(0x60)
++#define MT_RRO_PARTICULAR_CONFG_EN		BIT(31)
++#define MT_RRO_PARTICULAR_SID			GENMASK(30, 16)
++
++#define MT_RRO_BA_BITMAP_BASE_EXT0		MT_RRO_TOP(0x70)
++#define MT_RRO_BA_BITMAP_BASE_EXT1		MT_RRO_TOP(0x74)
++#define MT_RRO_HOST_INT_ENA			MT_RRO_TOP(0x204)
++#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA   BIT(0)
++
++#define MT_RRO_ADDR_ELEM_SEG_ADDR0		MT_RRO_TOP(0x400)
++
++#define MT_RRO_ACK_SN_CTRL			MT_RRO_TOP(0x50)
++#define MT_RRO_ACK_SN_CTRL_SN_MASK		GENMASK(27, 16)
++#define MT_RRO_ACK_SN_CTRL_SESSION_MASK		GENMASK(11, 0)
++
++
+ #define MT_MCU_INT_EVENT			0x2108
+ #define MT_MCU_INT_EVENT_DMA_STOPPED		BIT(0)
+ #define MT_MCU_INT_EVENT_DMA_INIT		BIT(1)
+@@ -391,6 +425,7 @@ enum base_rev {
+ #define MT_MCUQ_RING_BASE(q)			(MT_Q_BASE(q) + 0x300)
+ #define MT_TXQ_RING_BASE(q)			(MT_Q_BASE(__TXQ(q)) + 0x300)
+ #define MT_RXQ_RING_BASE(q)			(MT_Q_BASE(__RXQ(q)) + 0x500)
++#define MT_RXQ_RRO_IND_RING_BASE		MT_RRO_TOP(0x40)
+ 
+ #define MT_MCUQ_EXT_CTRL(q)			(MT_Q_BASE(q) +	0x600 +	\
+ 						 MT_MCUQ_ID(q) * 0x4)
+@@ -418,6 +453,15 @@ enum base_rev {
+ #define MT_INT_MCU_CMD				BIT(29)
+ #define MT_INT_RX_TXFREE_EXT			BIT(26)
+ 
++#define MT_INT_RX_DONE_RRO_BAND0		BIT(16)
++#define MT_INT_RX_DONE_RRO_BAND1		BIT(16)
++#define MT_INT_RX_DONE_RRO_BAND2		BIT(14)
++#define MT_INT_RX_DONE_RRO_IND			BIT(11)
++#define MT_INT_RX_DONE_MSDU_PG_BAND0		BIT(18)
++#define MT_INT_RX_DONE_MSDU_PG_BAND1		BIT(19)
++#define MT_INT_RX_DONE_MSDU_PG_BAND2		BIT(23)
++
++
+ #define MT_INT_RX(q)				(dev->q_int_mask[__RXQ(q)])
+ #define MT_INT_TX_MCU(q)			(dev->q_int_mask[(q)])
+ 
+@@ -425,20 +469,31 @@ enum base_rev {
+ 						 MT_INT_RX(MT_RXQ_MCU_WA))
+ 
+ #define MT_INT_BAND0_RX_DONE			(MT_INT_RX(MT_RXQ_MAIN) |	\
+-						 MT_INT_RX(MT_RXQ_MAIN_WA))
++						 MT_INT_RX(MT_RXQ_MAIN_WA) |	\
++						 MT_INT_RX(MT_RXQ_TXFREE_BAND0))
+ 
+ #define MT_INT_BAND1_RX_DONE			(MT_INT_RX(MT_RXQ_BAND1) |	\
+ 						 MT_INT_RX(MT_RXQ_BAND1_WA) |	\
+-						 MT_INT_RX(MT_RXQ_MAIN_WA))
++						 MT_INT_RX(MT_RXQ_MAIN_WA) |	\
++						 MT_INT_RX(MT_RXQ_TXFREE_BAND0))
+ 
+ #define MT_INT_BAND2_RX_DONE			(MT_INT_RX(MT_RXQ_BAND2) |	\
+ 						 MT_INT_RX(MT_RXQ_BAND2_WA) |	\
+-						 MT_INT_RX(MT_RXQ_MAIN_WA))
++						 MT_INT_RX(MT_RXQ_MAIN_WA) |	\
++						 MT_INT_RX(MT_RXQ_TXFREE_BAND0))
++
++#define MT_INT_RRO_RX_DONE			(MT_INT_RX(MT_RXQ_RRO_BAND0) |		\
++						 MT_INT_RX(MT_RXQ_RRO_BAND1) |		\
++						 MT_INT_RX(MT_RXQ_RRO_BAND2) |		\
++						 MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) |	\
++						 MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) |	\
++						 MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
+ 
+ #define MT_INT_RX_DONE_ALL			(MT_INT_RX_DONE_MCU |		\
+ 						 MT_INT_BAND0_RX_DONE |		\
+ 						 MT_INT_BAND1_RX_DONE |		\
+-						 MT_INT_BAND2_RX_DONE)
++						 MT_INT_BAND2_RX_DONE |		\
++						 MT_INT_RRO_RX_DONE)
+ 
+ #define MT_INT_TX_DONE_FWDL			BIT(26)
+ #define MT_INT_TX_DONE_MCU_WM			BIT(27)
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch
new file mode 100644
index 0000000..7fdee4c
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch
@@ -0,0 +1,50 @@
+From e5136e5f940adf55f1e7604960dba89e24a187bb Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 13 Apr 2023 14:12:16 +0800
+Subject: [PATCH 2005/2008] wifi: mt76: mt7996: wed: add mt7996_net_setup_tc to
+ support wifi2wifi offload
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt7996/main.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 50fa6523..cebac4ab 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -1446,6 +1446,24 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
+ 	return 0;
+ }
+ 
++static int mt7996_net_setup_tc(struct ieee80211_hw *hw,
++			       struct ieee80211_vif *vif,
++			       struct net_device *ndev,
++			       enum tc_setup_type type,
++			       void *type_data)
++
++{
++	struct mt7996_dev *dev = mt7996_hw_dev(hw);
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++
++	if (!mtk_wed_device_active(wed))
++		return -ENODEV;
++
++	mtk_wed_device_setup_tc(wed, ndev, type, type_data);
++
++	return 0;
++}
++
+ #endif
+ 
+ const struct ieee80211_ops mt7996_ops = {
+@@ -1496,5 +1514,6 @@ const struct ieee80211_ops mt7996_ops = {
+ 	.set_radar_background = mt7996_set_radar_background,
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ 	.net_fill_forward_path = mt7996_net_fill_forward_path,
++	.net_setup_tc = mt7996_net_setup_tc,
+ #endif
+ };
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch
new file mode 100644
index 0000000..7902639
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2006-wifi-mt76-add-random-early-drop-support.patch
@@ -0,0 +1,144 @@
+From fba98d69dcbbbcbd4cbf61e997637ecead9e55a3 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Wed, 19 Apr 2023 18:32:41 +0800
+Subject: [PATCH 2006/2008] wifi: mt76: add random early drop support
+
+---
+ mt7996/mcu.c    | 77 +++++++++++++++++++++++++++++++++++++++++++++++--
+ mt7996/mcu.h    |  4 ++-
+ mt7996/mt7996.h |  1 +
+ 3 files changed, 79 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 1891c0d7..0c01e90b 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2933,8 +2933,8 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	return mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+-				 MCU_WA_PARAM_RED, 0, 0);
++	return mt7996_mcu_red_config(dev,
++			mtk_wed_device_active(&dev->mt76.mmio.wed));
+ }
+ 
+ int mt7996_mcu_init(struct mt7996_dev *dev)
+@@ -2966,6 +2966,79 @@ out:
+ 	skb_queue_purge(&dev->mt76.mcu.res_q);
+ }
+ 
++static int mt7996_mcu_wa_red_config(struct mt7996_dev *dev)
++{
++#define RED_TOKEN_SRC_CNT	4
++#define RED_TOKEN_CONFIG	2
++	struct {
++		__le32 arg0;
++		__le32 arg1;
++		__le32 arg2;
++
++		u8 mode;
++		u8 version;
++		u8 _rsv[4];
++		__le16 len;
++
++		__le16 tcp_offset;
++		__le16 priority_offset;
++		__le16 token_per_src[RED_TOKEN_SRC_CNT];
++		__le16 token_thr_per_src[RED_TOKEN_SRC_CNT];
++
++		u8 _rsv2[604];
++	} __packed req = {
++		.arg0 = cpu_to_le32(MCU_WA_PARAM_RED_CONFIG),
++
++		.mode = RED_TOKEN_CONFIG,
++		.len = cpu_to_le16(sizeof(req) - sizeof(__le32) * 3),
++
++		.tcp_offset = cpu_to_le16(200),
++		.priority_offset = cpu_to_le16(255),
++	};
++	u8 i;
++
++	for (i = 0; i < RED_TOKEN_SRC_CNT; i++) {
++		req.token_per_src[i] = cpu_to_le16(MT7996_TOKEN_SIZE);
++		req.token_thr_per_src[i] = cpu_to_le16(MT7996_TOKEN_SIZE);
++	}
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET),
++				 &req, sizeof(req), false);
++}
++
++int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable)
++{
++#define RED_DISABLE		0
++#define RED_BY_WA_ENABLE	2
++	struct {
++		u8 __rsv1[4];
++
++		__le16 tag;
++		__le16 len;
++		u8 enable;
++		u8 __rsv2[3];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_VOW_RED_ENABLE),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.enable = enable ? RED_BY_WA_ENABLE : RED_DISABLE,
++	};
++	int ret;
++
++	ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
++				 sizeof(req), true);
++
++	if (ret)
++		return ret;
++
++	ret = mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
++				MCU_WA_PARAM_RED_EN, enable, 0);
++
++	if (ret || !enable)
++		return ret;
++
++	return mt7996_mcu_wa_red_config(dev);
++}
++
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans)
+ {
+ 	struct {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index a0cbf922..ec074bc6 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -239,8 +239,9 @@ enum {
+ enum {
+ 	MCU_WA_PARAM_PDMA_RX = 0x04,
+ 	MCU_WA_PARAM_CPU_UTIL = 0x0b,
+-	MCU_WA_PARAM_RED = 0x0e,
++	MCU_WA_PARAM_RED_EN = 0x0e,
+ 	MCU_WA_PARAM_HW_PATH_HIF_VER = 0x2f,
++	MCU_WA_PARAM_RED_CONFIG = 0x40,
+ };
+ 
+ enum mcu_mmps_mode {
+@@ -695,6 +696,7 @@ enum {
+ 	UNI_VOW_DRR_CTRL,
+ 	UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
+ 	UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
++	UNI_VOW_RED_ENABLE = 0x18,
+ };
+ 
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 836c7db7..b239c44c 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -671,6 +671,7 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
+ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
++int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
+ int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
+ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
+ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
new file mode 100644
index 0000000..5897422
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
@@ -0,0 +1,473 @@
+From cc7283ecc1da9d4f62803062466fb5420d2ea766 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 18 May 2023 15:01:47 +0800
+Subject: [PATCH 2007/2008] wifi: mt76: mt7996: reset addr_elem when delete ba
+
+The old addr element info may be used when the signature is not equel to
+0xff, and sta will find error SDP cause the SDP/SDL=0 issue.
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt76.h            |   1 +
+ mt76_connac_mcu.h |   1 +
+ mt7996/init.c     |   3 +
+ mt7996/mac.c      | 140 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/main.c     |   7 +++
+ mt7996/mcu.c      |  64 +++++++++++++++++++++
+ mt7996/mcu.h      |  34 +++++++++++
+ mt7996/mt7996.h   |  32 +++++++++++
+ mt7996/regs.h     |   5 ++
+ 9 files changed, 287 insertions(+)
+
+diff --git a/mt76.h b/mt76.h
+index e4351338..7ebcf432 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -436,6 +436,7 @@ struct mt76_rx_tid {
+ 	u16 nframes;
+ 
+ 	u8 num;
++	u8 partial_id;
+ 
+ 	u8 started:1, stopped:1, timer_pending:1;
+ 
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index a53fa138..d74fd2dd 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1023,6 +1023,7 @@ enum {
+ 	MCU_UNI_EVENT_THERMAL = 0x35,
+ 	MCU_UNI_EVENT_BF = 0x33,
+ 	MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
++	MCU_UNI_EVENT_RRO = 0x57,
+ };
+ 
+ #define MCU_UNI_CMD_EVENT			BIT(1)
+diff --git a/mt7996/init.c b/mt7996/init.c
+index d70dcf9f..93262297 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -759,6 +759,9 @@ static int mt7996_rro_init(struct mt7996_dev *dev)
+ 	mt76_wr(dev, MT_RRO_HOST_INT_ENA,
+ 		MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
+ 
++	INIT_DELAYED_WORK(&dev->rro.rro_del_work, mt7996_rro_delete_sessions);
++	INIT_LIST_HEAD(&dev->rro.rro_poll_list);
++
+ 	/* rro ind cmd queue init */
+ 	return mt7996_dma_rro_init(dev);
+ }
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 4fbbc077..3a89013c 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1647,6 +1647,139 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 	}
+ }
+ 
++static struct mt7996_rro_addr *
++mt7996_rro_get_addr_elem(struct mt7996_dev *dev, u16 seid, u16 sn)
++{
++	struct mt7996_rro_cfg *rro = &dev->rro;
++	u32 idx;
++	void *addr;
++
++	if (seid == rro->particular_se_id) {
++		addr = rro->particular_session_va;
++		idx = sn % rro->win_sz;
++	} else {
++		addr = rro->addr_elem_alloc_va[seid / MT7996_RRO_SESSION_PER_CR];
++		idx = (seid % MT7996_RRO_SESSION_PER_CR) * rro->win_sz
++			+ (sn % rro->win_sz);
++	}
++	return addr + idx * sizeof(struct mt7996_rro_addr);
++}
++
++static bool mt7996_rro_reset_sessions(struct mt7996_dev *dev,
++				  u16 wcid, u8 partial_id)
++{
++	u32 sid = ((wcid & 0x7F) << 3) + partial_id;
++	u32 value[2];
++	struct mt7996_rro_ba_session *s;
++	struct  mt7996_rro_addr *elem;
++	int i;
++
++	mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC |
++		sid >> 1 | 0x200);
++
++	if (sid & 0x1) {
++		value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
++		value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
++	} else {
++		value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
++		value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
++	}
++
++	s = (struct mt7996_rro_ba_session *)&value[0];
++	if (!s->cn && s->ack_sn == s->last_in_sn) {
++		for (i = 0; i < MT7996_RRO_WIN_SIZE_MAX; i++) {
++			elem = mt7996_rro_get_addr_elem(dev, sid, i);
++			elem->signature = 0xff;
++		}
++		return true;
++	}
++
++	return false;
++}
++
++void  mt7996_rro_delete_sessions(struct work_struct *work)
++{
++	struct mt7996_dev *dev;
++	struct mt7996_rro_ba_session_elem *e;
++	int elem_nums;
++	LIST_HEAD(rro_poll_list);
++
++	dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
++					       rro.rro_del_work.work);
++	elem_nums = dev->rro.elem_nums;
++
++	spin_lock_bh(&dev->rro.rro_stbl_lock);
++	list_splice_init(&dev->rro.rro_poll_list, &rro_poll_list);
++	spin_unlock_bh(&dev->rro.rro_stbl_lock);
++
++	do {
++		spin_lock_bh(&dev->rro.rro_stbl_lock);
++		if (list_empty(&rro_poll_list)) {
++			spin_unlock_bh(&dev->rro.rro_stbl_lock);
++			break;
++		}
++
++		e = list_first_entry(&rro_poll_list,
++				     struct mt7996_rro_ba_session_elem,
++				     poll_list);
++		if (!e) {
++			spin_unlock_bh(&dev->rro.rro_stbl_lock);
++			break;
++		}
++		list_del_init(&e->poll_list);
++		spin_unlock_bh(&dev->rro.rro_stbl_lock);
++
++		if (mt7996_rro_reset_sessions(dev, e->wlan_idx,
++					      e->partial_id)) {
++			mt7996_mcu_reset_rro_sessions(dev, e->wlan_idx,
++						      e->tid, e->partial_id);
++			kfree(e);
++			dev->rro.elem_nums--;
++		} else {
++			spin_lock_bh(&dev->rro.rro_stbl_lock);
++			list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
++			spin_unlock_bh(&dev->rro.rro_stbl_lock);
++		}
++		elem_nums--;
++	} while (elem_nums);
++
++	if (list_empty(&rro_poll_list))
++		ieee80211_queue_delayed_work(mt76_hw(dev),
++					     &dev->rro.rro_del_work,
++					     MT7996_WATCHDOG_TIME);
++}
++
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
++			       struct mt7996_sta *msta, u8 tidno)
++{
++	struct mt76_rx_tid *tid = NULL;
++	struct mt76_wcid *wcid = &msta->wcid;
++	struct mt7996_rro_ba_session_elem *e;
++	u16 idx = msta->wcid.idx;
++
++	tid = rcu_dereference(wcid->aggr[tidno]);
++	if (!tid)
++		return 0;
++
++	e = kzalloc(sizeof(*e), GFP_ATOMIC);
++	if (!e)
++		return -ENOMEM;
++
++	e->wlan_idx = idx;
++	e->tid = tidno;
++	e->partial_id = tid->partial_id;
++
++	spin_lock_bh(&dev->rro.rro_stbl_lock);
++	list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
++	spin_unlock_bh(&dev->rro.rro_stbl_lock);
++	dev->rro.elem_nums++;
++
++	ieee80211_queue_delayed_work(mt76_hw(dev),
++				     &dev->rro.rro_del_work,
++				     MT7996_WATCHDOG_TIME);
++	return 0;
++}
++
+ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -1971,6 +2104,9 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ 	if (phy3)
+ 		ieee80211_stop_queues(phy3->mt76->hw);
+ 
++	if (dev->rro_support)
++		cancel_delayed_work_sync(&dev->rro.rro_del_work);
++
+ 	cancel_delayed_work_sync(&dev->mphy.mac_work);
+ 	if (phy2)
+ 		cancel_delayed_work_sync(&phy2->mt76->mac_work);
+@@ -2062,6 +2198,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	set_bit(MT76_RESET, &dev->mphy.state);
+ 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	wake_up(&dev->mt76.mcu.wait);
++
++	if (dev->rro_support)
++		cancel_delayed_work_sync(&dev->rro.rro_del_work);
++
+ 	cancel_delayed_work_sync(&dev->mphy.mac_work);
+ 	if (phy2) {
+ 		set_bit(MT76_RESET, &phy2->mt76->state);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index cebac4ab..4cb72220 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -119,6 +119,9 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+ 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 
++	if (dev->rro_support)
++		cancel_delayed_work_sync(&dev->rro.rro_del_work);
++
+ 	cancel_delayed_work_sync(&phy->mt76->mac_work);
+ 	cancel_delayed_work_sync(&dev->scs_work);
+ 
+@@ -797,6 +800,10 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		ret = mt7996_mcu_add_rx_ba(dev, params, true);
+ 		break;
+ 	case IEEE80211_AMPDU_RX_STOP:
++		if (dev->rro_support)  {
++			ret = mt7996_rro_add_delete_elem(dev, msta,
++							 params->tid);
++		}
+ 		mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
+ 		ret = mt7996_mcu_add_rx_ba(dev, params, false);
+ 		break;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 0c01e90b..094f3656 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -476,6 +476,41 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	phy->throttle_state = n->duty_percent;
+ }
+ 
++static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++	struct mt7996_mcu_rro_event *event;
++
++	if (!dev->rro_support)
++		return;
++
++	event = (struct mt7996_mcu_rro_event*)skb->data;
++
++	switch (event->tag) {
++	case UNI_RRO_BA_SESSION_STATUS: {
++		struct mt7996_mcu_rro_ba *rro = (struct mt7996_mcu_rro_ba *)skb->data;
++		u16 idx = rro->wlan_id;
++		struct mt76_rx_tid *tid;
++		struct mt76_wcid *wcid;
++
++		wcid = rcu_dereference(dev->mt76.wcid[idx]);
++		if (!wcid || !wcid->sta)
++			return;
++
++		tid = rcu_dereference(wcid->aggr[rro->tid]);
++		if (!tid)
++			return;
++		tid->partial_id = rro->partial_id;
++
++		break;
++	}
++	default:
++		dev_info(dev->mt76.dev, "%s: unknown rro event tag %d\n",
++			 __func__, event->tag);
++		break;
++	}
++
++}
++
+ static void
+ mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -528,6 +563,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 		mt7996_tm_rf_test_event(dev, skb);
+ 		break;
+ #endif
++	case MCU_UNI_EVENT_RRO:
++		mt7996_mcu_rx_rro(dev, skb);
++		break;
+ 	default:
+ 		break;
+ 	}
+@@ -4533,6 +4571,32 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ 				 sizeof(req), true);
+ }
+ 
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
++					 u16 wcid, u8 tid, u8 pid)
++{
++	struct {
++		/* fixed field */
++		u8 __rsv[4];
++
++		__le16 tag;
++		__le16 len;
++		u16 wcid;
++		u8 tid;
++		u8 partial_id;
++		u8 pad[4];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.wcid = wcid,
++		.tid = tid,
++		.partial_id = pid,
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WMWA_UNI_CMD(RRO),
++				 &req, sizeof(req), true);
++}
++
++
+ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index ec074bc6..10e3799f 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -191,6 +191,38 @@ struct mt7996_mcu_thermal_notify {
+ 	u8 __rsv2[4];
+ } __packed;
+ 
++struct mt7996_mcu_rro_event {
++	struct mt7996_mcu_rxd rxd;
++
++	u8 __rsv1[4];
++
++	__le16 tag;
++	__le16 len;
++} __packed;
++
++struct mt7996_mcu_rro_ba {
++	struct mt7996_mcu_rro_event event;
++
++	u16 wlan_id;
++	u8 tid;
++	u8 partial_id;
++	__le32 status;
++}__packed;
++
++enum  {
++	UNI_RRO_BA_SESSION_STATUS = 0,
++	UNI_RRO_BA_SESSION_TBL	= 1,
++	UNI_RRO_BA_SESSION_MAX_NUM
++};
++
++struct mt7996_mcu_rro_del_ba {
++	struct mt7996_mcu_rro_event event;
++
++	u8  wlan_idx;
++	u8  tid;
++	u8 __rsv2[2];
++};
++
+ enum mt7996_chan_mib_offs {
+ 	UNI_MIB_OBSS_AIRTIME = 26,
+ 	UNI_MIB_NON_WIFI_TIME = 27,
+@@ -718,6 +750,8 @@ enum {
+ 	UNI_RRO_GET_BA_SESSION_TABLE,
+ 	UNI_RRO_SET_BYPASS_MODE,
+ 	UNI_RRO_SET_TXFREE_PATH,
++	UNI_RRO_DEL_BA_SESSION,
++	UNI_RRO_SET_FLUSH_TIMEOUT
+ };
+ 
+ enum{
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index b239c44c..88d42c3a 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -310,6 +310,28 @@ struct mt7996_rro_addr {
+ 	u32 signature	: 8;
+ };
+ 
++struct mt7996_rro_ba_session {
++	u32 ack_sn         :12;
++	u32 win_sz         :3;
++	u32 bn             :1;
++	u32 last_in_sn     :12;
++	u32 bc             :1;
++	u32 bd             :1;
++	u32 sat            :1;
++	u32 cn             :1;
++	u32 within_cnt     :12;
++	u32 to_sel         :3;
++	u32 rsv            :1;
++	u32 last_in_rxtime :12;
++};
++
++struct mt7996_rro_ba_session_elem {
++	struct list_head poll_list;
++	u16 wlan_idx;
++	u8 tid;
++	u8 partial_id;
++};
++
+ struct mt7996_rro_cfg {
+ 	u32 ind_signature;
+ 	void *ba_bitmap_cache_va[MT7996_RRO_BA_BITMAP_CR_CNT];
+@@ -324,6 +346,11 @@ struct mt7996_rro_cfg {
+ 	spinlock_t lock;
+ 	struct list_head pg_addr_cache;
+ 	struct list_head pg_hash_head[MT7996_RRO_MSDU_PG_HASH_SIZE];
++
++	struct delayed_work rro_del_work;
++	spinlock_t rro_stbl_lock;
++	struct list_head rro_poll_list;
++	u16 elem_nums;
+ };
+ 
+ struct mt7996_phy {
+@@ -670,6 +697,8 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
++				     u16 wcid, u8 tid, u8 pid);
+ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
+ int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
+ int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
+@@ -768,6 +797,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 			  struct mt76_tx_info *tx_info);
+ void mt7996_tx_token_put(struct mt7996_dev *dev);
+ int mt7996_dma_rro_init(struct mt7996_dev *dev);
++void  mt7996_rro_delete_sessions(struct work_struct *work);
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
++			       struct mt7996_sta *msta, u8 tid);
+ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 			 struct sk_buff *skb, u32 *info);
+ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 6624685e..f97c87c9 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -72,6 +72,11 @@ enum base_rev {
+ #define MT_RRO_ACK_SN_CTRL_SN_MASK		GENMASK(27, 16)
+ #define MT_RRO_ACK_SN_CTRL_SESSION_MASK		GENMASK(11, 0)
+ 
++#define MT_RRO_DBG_RD_CTRL			MT_RRO_TOP(0xe0)
++#define MT_RRO_DBG_RD_ADDR			GENMASK(15, 0)
++#define MT_RRO_DBG_RD_EXEC			BIT(31)
++
++#define MT_RRO_DBG_RDAT_DW(_n)			MT_RRO_TOP(0xf0 + _n * 0x4)
+ 
+ #define MT_MCU_INT_EVENT			0x2108
+ #define MT_MCU_INT_EVENT_DMA_STOPPED		BIT(0)
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch b/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch
new file mode 100644
index 0000000..0d2134b
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/2008-wifi-mt76-add-SER-support-for-wed3.0.patch
@@ -0,0 +1,303 @@
+From 5df084a32eac68dd66a3b833cf5f718118850b08 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Tue, 23 May 2023 12:06:29 +0800
+Subject: [PATCH 2008/2008] wifi: mt76: add SER support for wed3.0
+
+Change-Id: I2711b9dc336fca9a1ae32a8fbf27810a7e27b1e3
+---
+ dma.c         |  7 +++++--
+ mt7996/dma.c  | 48 +++++++++++++++++++++++++++++++++++++++++++++---
+ mt7996/mac.c  | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ mt7996/mmio.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 145 insertions(+), 6 deletions(-)
+
+diff --git a/dma.c b/dma.c
+index e5b4d898..e31f6390 100644
+--- a/dma.c
++++ b/dma.c
+@@ -770,8 +770,9 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+ 				q->head = q->ndesc - 1;
+ 				q->queued = q->ndesc - 1;
+ 			}
++			q->flags = flags;
+ 		} else {
+-			ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, 0);
++			ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
+ 			if (!ret)
+ 				q->wed_regs = wed->rx_ring[ring].reg_base;
+ 		}
+@@ -902,7 +903,9 @@ done:
+ 
+ 	/* reset WED rx queues */
+ 	mt76_dma_wed_setup(dev, q, true);
+-	if (q->flags != MT_WED_Q_TXFREE) {
++	if (q->flags != MT_WED_Q_TXFREE &&
++	    !((q->flags & MT_QFLAG_RRO) &&
++	    mtk_wed_device_active(&dev->mmio.wed))) {
+ 		mt76_dma_sync_idx(dev, q);
+ 		mt76_dma_rx_fill(dev, q);
+ 	}
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index c5c7f160..471ae81c 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -495,6 +495,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	if (mt7996_band_valid(dev, MT_BAND2)) {
+ 		/* rx data queue for band2 */
+ 		rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
++		if (mtk_wed_device_active(wed)) {
++			rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
++			if (mtk_wed_get_rx_capa(wed))
++				dev->mt76.q_rx[MT_RXQ_BAND2].flags = MT_WED_Q_RX(1);
++		}
++
+ 		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
+ 				       MT_RXQ_ID(MT_RXQ_BAND2),
+ 				       MT7996_RX_RING_SIZE,
+@@ -582,11 +588,35 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	return 0;
+ }
+ 
++static void mt7996_dma_wed_reset(struct mt7996_dev *dev)
++{
++	struct mt76_dev *mdev = &dev->mt76;
++
++	if (!test_bit(MT76_STATE_WED_RESET, &dev->mphy.state))
++		return;
++
++	complete(&mdev->mmio.wed_reset);
++
++	if (!wait_for_completion_timeout(&dev->mt76.mmio.wed_reset_complete,
++					 3 * HZ))
++		dev_err(dev->mt76.dev, "wed reset complete timeout\n");
++}
++
++static void
++mt7996_dma_reset_tx_queue(struct mt7996_dev *dev, struct mt76_queue *q)
++{
++	mt76_queue_reset(dev, q, false);
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		mt76_dma_wed_setup(&dev->mt76, q, true);
++}
++
+ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+ {
+ 	struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
+ 	struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
+ 	u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
++	struct mtk_wed_device *wed_ext = &dev->mt76.mmio.wed_ext;
+ 	int i;
+ 
+ 	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+@@ -620,21 +650,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+ 	if (force)
+ 		mt7996_wfsys_reset(dev);
+ 
++	if (dev->hif2 && mtk_wed_device_active(wed_ext))
++		mtk_wed_device_dma_reset(wed_ext);
++
++	if (mtk_wed_device_active(wed))
++		mtk_wed_device_dma_reset(wed);
++
+ 	mt7996_dma_disable(dev, force);
++	mt7996_dma_wed_reset(dev);
+ 
+ 	/* reset hw queues */
+ 	for (i = 0; i < __MT_TXQ_MAX; i++) {
+-		mt76_queue_reset(dev, dev->mphy.q_tx[i], false);
++		mt7996_dma_reset_tx_queue(dev, dev->mphy.q_tx[i]);
+ 		if (phy2)
+-			mt76_queue_reset(dev, phy2->q_tx[i], false);
++			mt7996_dma_reset_tx_queue(dev, phy2->q_tx[i]);
+ 		if (phy3)
+-			mt76_queue_reset(dev, phy3->q_tx[i], false);
++			mt7996_dma_reset_tx_queue(dev, phy3->q_tx[i]);
+ 	}
+ 
+ 	for (i = 0; i < __MT_MCUQ_MAX; i++)
+ 		mt76_queue_reset(dev, dev->mt76.q_mcu[i], false);
+ 
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
++		if (mtk_wed_device_active(wed) &&
++		    ((dev->mt76.q_rx[i].flags & MT_QFLAG_RRO) ||
++		    dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE))
++			continue;
++
+ 		mt76_queue_reset(dev, &dev->mt76.q_rx[i], false);
+ 	}
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 3a89013c..d1082e89 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2002,6 +2002,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+ 	/* disable all tx/rx napi */
+ 	mt76_worker_disable(&dev->mt76.tx_worker);
+ 	mt76_for_each_q_rx(mdev, i) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    (mdev->q_rx[i].flags & MT_QFLAG_RRO))
++			continue;
++
+ 		if (mdev->q_rx[i].ndesc)
+ 			napi_disable(&dev->mt76.napi[i]);
+ 	}
+@@ -2015,6 +2019,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
+ 
+ 	local_bh_disable();
+ 	mt76_for_each_q_rx(mdev, i) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    (mdev->q_rx[i].flags & MT_QFLAG_RRO))
++			continue;
++
+ 		if (mdev->q_rx[i].ndesc) {
+ 			napi_enable(&dev->mt76.napi[i]);
+ 			napi_schedule(&dev->mt76.napi[i]);
+@@ -2189,6 +2197,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 
+ 	dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
+ 		 wiphy_name(dev->mt76.hw->wiphy));
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext))
++		mtk_wed_device_stop(&dev->mt76.mmio.wed_ext);
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
++		mtk_wed_device_stop(&dev->mt76.mmio.wed);
++
+ 	ieee80211_stop_queues(mt76_hw(dev));
+ 	if (phy2)
+ 		ieee80211_stop_queues(phy2->mt76->hw);
+@@ -2212,8 +2227,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 		cancel_delayed_work_sync(&phy3->mt76->mac_work);
+ 	}
+ 	mt76_worker_disable(&dev->mt76.tx_worker);
+-	mt76_for_each_q_rx(&dev->mt76, i)
++	mt76_for_each_q_rx(&dev->mt76, i) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    (dev->mt76.q_rx[i].flags & MT_QFLAG_RRO))
++			continue;
++
+ 		napi_disable(&dev->mt76.napi[i]);
++	}
+ 	napi_disable(&dev->mt76.tx_napi);
+ 
+ 	mutex_lock(&dev->mt76.mutex);
+@@ -2236,6 +2256,29 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	/* enable dma tx/rx and interrupt */
+ 	__mt7996_dma_enable(dev, false, false);
+ 
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
++		u32 wed_irq_mask = dev->mt76.mmio.irqmask |
++				   MT_INT_RRO_RX_DONE |
++				   MT_INT_TX_DONE_BAND2;
++
++		if (mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
++			wed_irq_mask &= ~MT_INT_RX_DONE_RRO_IND;
++
++		mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
++
++		mtk_wed_device_start_hwrro(&dev->mt76.mmio.wed, wed_irq_mask, true);
++		mt7996_irq_enable(dev, wed_irq_mask);
++		mt7996_irq_disable(dev, 0);
++	}
++
++	if (mtk_wed_device_active(&dev->mt76.mmio.wed_ext)) {
++		mt76_wr(dev, MT_INT1_MASK_CSR,
++			dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2);
++		mtk_wed_device_start(&dev->mt76.mmio.wed_ext,
++			dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2);
++	}
++
+ 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	clear_bit(MT76_RESET, &dev->mphy.state);
+ 	if (phy2)
+@@ -2245,6 +2288,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 
+ 	local_bh_disable();
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
++		if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
++		    ((dev->mt76.q_rx[i].flags & MT_QFLAG_RRO)))
++			continue;
++
+ 		napi_enable(&dev->mt76.napi[i]);
+ 		napi_schedule(&dev->mt76.napi[i]);
+ 	}
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 9960dca7..fe34bb7d 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -6,9 +6,11 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
++#include <linux/rtnetlink.h>
+ 
+ #include "mt7996.h"
+ #include "mac.h"
++#include "mcu.h"
+ #include "../trace.h"
+ #include "../dma.h"
+ 
+@@ -297,6 +299,43 @@ unmap:
+ 	mt7996_mmio_wed_release_rx_buf(wed);
+ 	return -ENOMEM;
+ }
++
++static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
++{
++	struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed);
++	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++	struct mt76_phy *mphy = &dev->mphy;
++	int ret;
++
++	ASSERT_RTNL();
++
++	if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
++		return -EBUSY;
++
++	ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
++				 mphy->band_idx);
++	if (ret)
++		goto out;
++
++	rtnl_unlock();
++	if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) {
++		dev_err(mdev->dev, "wed reset timeout\n");
++		ret = -ETIMEDOUT;
++	}
++	rtnl_lock();
++out:
++	clear_bit(MT76_STATE_WED_RESET, &mphy->state);
++
++	return ret;
++}
++
++static void mt7996_mmio_wed_reset_complete(struct mtk_wed_device *wed)
++{
++	struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
++
++	complete(&dev->mmio.wed_reset_complete);
++}
++
+ #endif
+ 
+ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+@@ -421,6 +460,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
+ 	wed->wlan.init_rx_buf = mt7996_mmio_wed_init_rx_buf;
+ 	wed->wlan.release_rx_buf = mt7996_mmio_wed_release_rx_buf;
+ 	wed->wlan.update_wo_rx_stats = NULL;
++	if (hif2) {
++		wed->wlan.reset = NULL;
++		wed->wlan.reset_complete = NULL;
++	} else {
++		wed->wlan.reset = mt7996_mmio_wed_reset;
++		wed->wlan.reset_complete = mt7996_mmio_wed_reset_complete;
++	}
++
+ 
+ 	if (mtk_wed_device_attach(wed))
+ 		return 0;
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
index 12953cf..3114ebf 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
@@ -1,28 +1,66 @@
 #patch patches (come from openwrt/lede/target/linux/mediatek)
 SRC_URI_append = " \
     file://0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch \
-    file://0002-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch \
-    file://0003-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch \
-    file://0004-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
-    file://0005-wifi-mt76-mt7996-add-muru-support.patch \
-    file://0006-wifi-mt76-mt7996-set-txd-v1.patch \
-    file://0007-wifi-mt76-mt7996-add-thermal-protection-support.patch \
-    file://0008-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
-    file://0009-wifi-mt76-mt7996-add-dsp-firmware-download.patch \
-    file://0010-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch \
-    file://0011-wifi-mt76-mt7996-set-wcid-in-txp.patch \
-    file://0012-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch \
-    file://0013-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch \
-    file://0014-wifi-mt76-mt7996-Fix-using-the-wrong-phy-for-backgro.patch \
-    file://0015-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch \
-    file://0016-wifi-mt76-mt7996-fill-txwi-by-SW-temporarily.patch \
-    file://0017-wifi-mt76-mt7996-update-wmm-queue-mapping.patch \
-    file://0018-wifi-mt76-mt7996-enable-IDS-debug-log.patch \
-    file://0019-mt76-testmode-add-atenl-support-in-mt7996.patch \
-    file://0020-mt76-testmode-add-basic-testmode-support.patch \
-    file://0021-mt76-testmode-add-chainmask-hacking-for-eagle-band-2.patch \
-    file://0022-mt76-revert-page-pool-changes.patch \
-    file://0999-mt76-mt7996-for-build-pass.patch \
-    file://1000-mt76-mt7996-add-debug-tool.patch \
-    file://1001-mt76-mt7996-add-txpower-support.patch \
+    file://0002-wifi-mt76-mt7996-move-radio-ctrl-commands-to-proper-.patch \
+    file://0003-wifi-mt76-connac-add-support-for-dsp-firmware-downlo.patch \
+    file://0004-wifi-mt76-mt7996-fix-bss-wlan_idx-when-sending-bss_i.patch \
+    file://0005-wifi-mt76-mt7996-init-he-and-eht-cap-for-AP_VLAN.patch \
+    file://0006-wifi-mt76-mt7996-enable-VHT-extended-NSS-BW-feature.patch \
+    file://0007-wifi-mt76-connac-add-support-to-set-ifs-time-by-mcu-.patch \
+    file://0008-wifi-mt76-mt7996-use-correct-phy-for-background-rada.patch \
+    file://0009-wifi-mt76-mt7996-fix-WA-event-ring-size.patch \
+    file://0010-wifi-mt76-mt7996-add-muru-support.patch \
+    file://0011-wifi-mt76-mt7996-increase-tx-token-size.patch \
+    file://0014-wifi-mt76-mt7996-set-wcid-in-txp.patch \
+    file://0015-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch \
+    file://0016-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
+    file://0017-wifi-mt76-mt7996-add-thermal-protection-support.patch \
+    file://0018-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
+    file://0019-wifi-mt76-mt7996-fix-beamform-mcu-cmd-configuration.patch \
+    file://0020-wifi-mt76-mt7996-support-more-options-in-.set_bitrat.patch \
+    file://0021-wifi-mt76-mt7996-update-wmm-queue-mapping.patch \
+    file://0022-wifi-mt76-mt7996-enable-IDS-debug-log.patch \
+    file://0023-wifi-mt76-testmode-add-atenl-support-in-mt7996.patch \
+    file://0024-wifi-mt76-testmode-add-basic-testmode-support.patch \
+    file://0026-wifi-mt76-mt7996-add-led-feature-support.patch \
+    file://0027-wifi-mt76-mt7996-fix-twt-mcu-command.patch \
+    file://0028-wifi-mt76-mt7996-add-11v-mbss-support-for-mt76.patch \
+    file://0029-wifi-mt76-mt7996-Update-beacon-size-limitation-for-1.patch \
+    file://0030-wifi-mt76-mt7996-add-support-for-auxiliary-path.patch \
+    file://0031-wifi-mt76-mt7996-fix-memory-leak.patch \
+    file://0032-wifi-mt76-mt7996-add-eht-mode-tx-stats.patch \
+    file://0033-wifi-mt76-mt7996-disable-wfdma-tx-rx-during-SER.patch \
+    file://0034-wifi-mt76-mt7996-add-firmware-WA-s-coredump.patch \
+    file://0035-wifi-mt76-mt7996-make-band-capability-init-flexible.patch \
+    file://0036-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-drive.patch \
+    file://0037-wifi-mt76-mt7996-add-beacon-duplicate-tx-mode-suppor.patch \
+    file://0038-wifi-mt76-mt7996-fix-DFS-CAC-tx-emission-issue-after.patch \
+    file://0039-wifi-mt76-mt7996-fix-bss-rate-tlv-to-sync-firmware-c.patch \
+    file://0040-wifi-mt76-mt7996-fix-beamformee-ss-subfield-in-EHT-P.patch \
+    file://0999-wifi-mt76-mt7996-for-build-pass.patch \
+    file://1000-wifi-mt76-mt7996-add-debug-tool.patch \
+    file://1001-wifi-mt76-mt7996-add-txpower-support.patch \
+    file://1002-wifi-mt76-mt7996-add-mu-vendor-command-support.patch \
+    file://1003-wifi-mt76-mt7996-Add-air-monitor-support.patch \
+    file://1004-wifi-mt76-mt7996-add-driver-support-for-wpa3-ocv-and.patch \
+    file://1005-wifi-mt76-mt7996-add-U-NII-4-support.patch \
+    file://1006-wifi-mt76-testmode-add-testmode-pre-calibration-supp.patch \
+    file://1007-wifi-mt76-mt7996-add-binfile-mode-support.patch \
+    file://1008-wifi-mt76-mt7996-add-normal-mode-pre-calibration-sup.patch \
+    file://1009-wifi-mt76-mt7996-Beacon-protection-feature-added.patch \
+    file://1010-wifi-mt76-testmode-add-testmode-ZWDFS-verification-s.patch \
+    file://1011-wifi-mt76-mt7996-add-single-sku.patch \
+    file://1012-wifi-mt76-mt7996-add-vendor-cmd-to-get-available-col.patch \
+    file://1013-wifi-mt76-mt7996-get-tx_retries-and-tx_fails-from-tx.patch \
+    file://1014-wifi-mt76-mt7996-add-debugfs-for-fw-coredump.patch \
+    file://1015-wifi-mt76-mt7996-add-support-for-runtime-set-in-band.patch \
+    file://2000-wifi-mt76-rework-wed-rx-flow.patch \
+    file://2001-wifi-mt76-revert-page_poll-for-kernel-5.4.patch \
+    file://2002-wifi-mt76-wed-change-wed-token-init-size-to-adapt-we.patch \
+    file://2003-wifi-mt76-mt7996-wed-add-wed3.0-tx-support.patch \
+    file://2004-wifi-mt76-mt7996-wed-add-wed3.0-rx-support.patch \
+    file://2005-wifi-mt76-mt7996-wed-add-mt7996_net_setup_tc-to-supp.patch \
+    file://2006-wifi-mt76-add-random-early-drop-support.patch \
+    file://2007-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch \
+    file://2008-wifi-mt76-add-SER-support-for-wed3.0.patch \
     "
diff --git a/recipes-wifi/linux-mt76/files/patches/1010-wifi-mt76-testmode-additional-supports.patch b/recipes-wifi/linux-mt76/files/patches/1010-wifi-mt76-testmode-additional-supports.patch
index cbdece6..7902ebc 100644
--- a/recipes-wifi/linux-mt76/files/patches/1010-wifi-mt76-testmode-additional-supports.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1010-wifi-mt76-testmode-additional-supports.patch
@@ -1,32 +1,32 @@
-From 29deaa7cb606cf334238cb36d89891fa80bef0fc Mon Sep 17 00:00:00 2001
+From c311d022536c9c6be72f8e4a134f9dbaed13cd6d Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 21 Apr 2022 15:43:19 +0800
-Subject: [PATCH 1010/1033] wifi: mt76: testmode: additional supports
+Subject: [PATCH 1010/1014] wifi: mt76: testmode: additional supports
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  dma.c             |    3 +-
  mac80211.c        |   12 +
- mt76.h            |  108 ++++-
+ mt76.h            |  108 +++-
  mt76_connac_mcu.c |    4 +
  mt76_connac_mcu.h |    2 +
  mt7915/eeprom.c   |    2 +-
  mt7915/init.c     |    2 +-
  mt7915/mac.c      |   39 +-
  mt7915/main.c     |    2 +-
- mt7915/mcu.c      |   19 +-
+ mt7915/mcu.c      |   22 +-
  mt7915/mcu.h      |   29 +-
  mt7915/mmio.c     |    2 +
  mt7915/mt7915.h   |   16 +-
  mt7915/regs.h     |    3 +
- mt7915/testmode.c | 1184 ++++++++++++++++++++++++++++++++++++++++++---
+ mt7915/testmode.c | 1221 ++++++++++++++++++++++++++++++++++++++++++---
  mt7915/testmode.h |  278 +++++++++++
- testmode.c        |  280 +++++++++--
+ testmode.c        |  282 +++++++++--
  testmode.h        |   75 +++
  tools/fields.c    |   84 +++-
  tx.c              |    3 +-
- 20 files changed, 1991 insertions(+), 156 deletions(-)
+ 20 files changed, 2023 insertions(+), 166 deletions(-)
 
 diff --git a/dma.c b/dma.c
 index c9d2671..fc92e39 100644
@@ -398,7 +398,7 @@
  		mvif->mt76.wmm_idx += 2;
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 5a68bb7..e4ab3e0 100644
+index 5a68bb7..5cea513 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -387,6 +387,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -421,7 +421,17 @@
  	    !rxd->seq)
  		mt7915_mcu_rx_unsolicited_event(dev, skb);
  	else
-@@ -2781,21 +2787,21 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
+@@ -2713,7 +2719,8 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
+ 	}
+ #endif
+ 
+-	if (mt76_connac_spe_idx(phy->mt76->antenna_mask))
++	if (mt76_connac_spe_idx(phy->mt76->antenna_mask) &&
++	    !mt76_testmode_enabled(phy->mt76))
+ 		req.tx_path_num = fls(phy->mt76->antenna_mask);
+ 
+ 	if (dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
+@@ -2781,21 +2788,21 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
  	return 0;
  }
  
@@ -446,7 +456,7 @@
  {
  	struct mt7915_mcu_eeprom_info req = {
  		.addr = cpu_to_le32(round_down(offset,
-@@ -2804,7 +2810,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
+@@ -2804,7 +2811,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
  	struct mt7915_mcu_eeprom_info *res;
  	struct sk_buff *skb;
  	int ret;
@@ -455,7 +465,7 @@
  
  	ret = mt76_mcu_send_and_get_msg(&dev->mt76,
  					MCU_EXT_QUERY(EFUSE_ACCESS),
-@@ -2813,8 +2819,11 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
+@@ -2813,8 +2820,11 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
  		return ret;
  
  	res = (struct mt7915_mcu_eeprom_info *)skb->data;
@@ -595,7 +605,7 @@
  static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
  {
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index e7bc181..0339d4b 100644
+index e7bc181..b6f36f5 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -62,6 +62,7 @@ enum offs_rev {
@@ -611,12 +621,12 @@
  #define MT_WF_AGG(_band, ofs)		(MT_WF_AGG_BASE(_band) + (ofs))
  
 +#define MT_AGG_AALCR0(_band, _n)	MT_WF_AGG(_band, (__OFFS(AGG_AALCR0) +	\
-+			                                  (_n) * 4))
++							  (_n) * 4))
  #define MT_AGG_AWSCR0(_band, _n)	MT_WF_AGG(_band, (__OFFS(AGG_AWSCR0) +	\
  							  (_n) * 4))
  #define MT_AGG_PCR0(_band, _n)		MT_WF_AGG(_band, (__OFFS(AGG_PCR0) +	\
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 4693919..c44f13f 100644
+index 4693919..62ef4db 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -9,6 +9,9 @@
@@ -639,7 +649,7 @@
  };
  
  struct reg_band {
-@@ -33,6 +39,38 @@ struct reg_band {
+@@ -33,6 +39,57 @@ struct reg_band {
  #define TM_REG_MAX_ID	20
  static struct reg_band reg_backup_list[TM_REG_MAX_ID];
  
@@ -664,6 +674,25 @@
 +	return width_to_bw[width];
 +}
 +
++static int
++mt7915_tm_check_antenna(struct mt7915_phy *phy)
++{
++	struct mt76_testmode_data *td = &phy->mt76->test;
++	struct mt7915_dev *dev = phy->dev;
++	u8 band_idx = phy->mt76->band_idx;
++	u32 chainmask = phy->mt76->chainmask;
++
++	chainmask = chainmask >> (dev->chainshift * band_idx);
++	if (td->tx_antenna_mask & ~chainmask) {
++		dev_err(dev->mt76.dev,
++			"tx antenna mask %d exceeds hardware limitation (chainmask %d)\n",
++			td->tx_antenna_mask, chainmask);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
 +static void
 +mt7915_tm_update_channel(struct mt7915_phy *phy)
 +{
@@ -678,7 +707,7 @@
  
  static int
  mt7915_tm_set_tx_power(struct mt7915_phy *phy)
-@@ -119,18 +157,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
+@@ -119,18 +176,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
  }
  
  static int
@@ -711,7 +740,7 @@
  }
  
  static int
-@@ -141,7 +189,7 @@ mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control)
+@@ -141,7 +208,7 @@ mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control)
  		.testmode_en = 1,
  		.param_idx = MCU_ATE_SET_PHY_COUNT,
  		.param.cfg.enable = control,
@@ -720,7 +749,7 @@
  	};
  
  	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
-@@ -182,12 +230,738 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
+@@ -182,12 +249,738 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
  	return mt7915_mcu_set_muru_ctrl(dev, MURU_SET_ARB_OP_MODE, op_mode);
  }
  
@@ -1461,7 +1490,7 @@
  	struct edca *e = &req.edca[0];
  
  	e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
-@@ -263,7 +1037,8 @@ done:
+@@ -263,7 +1056,8 @@ done:
  
  	return mt7915_tm_set_wmm_qid(phy,
  				     mt76_connac_lmac_mapping(IEEE80211_AC_BE),
@@ -1471,7 +1500,7 @@
  }
  
  static int
-@@ -339,7 +1114,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
+@@ -339,7 +1133,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
  	bitrate = cfg80211_calculate_bitrate(&rate);
  	tx_len = bitrate * tx_time / 10 / 8;
  
@@ -1480,7 +1509,7 @@
  	if (ret)
  		return ret;
  
-@@ -458,64 +1233,227 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
+@@ -458,64 +1252,227 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
  
  	phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
  
@@ -1580,7 +1609,7 @@
 +	comm->spe_idx = phy->test.spe_idx;
 +
 +	dl->bw = mt7915_tm_chan_bw(chandef->width);
-+	dl->gi = td->tx_rate_sgi;;
++	dl->gi = td->tx_rate_sgi;
 +	dl->ltf = td->tx_ltf;
 +	dl->tx_mode = MT_PHY_TYPE_HE_MU;
 +
@@ -1739,7 +1768,7 @@
  
  	mt7915_tm_set_trx(phy, TM_MAC_TX, en);
  }
-@@ -544,10 +1482,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
+@@ -544,10 +1501,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
  		return ret;
  
  	rs_band = (struct mt7915_tm_rx_stat_band *)skb->data;
@@ -1750,7 +1779,7 @@
  
  	if (!clear) {
  		enum mt76_rxq_id q = req.band ? MT_RXQ_BAND1 : MT_RXQ_MAIN;
-@@ -562,13 +1496,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
+@@ -562,13 +1515,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
  	return 0;
  }
  
@@ -1813,7 +1842,7 @@
  
  		/* read-clear */
  		mt7915_tm_get_rx_stats(phy, true);
-@@ -576,9 +1558,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
+@@ -576,9 +1577,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
  		/* clear fw count */
  		mt7915_tm_set_phy_count(phy, 0);
  		mt7915_tm_set_phy_count(phy, 1);
@@ -1828,7 +1857,7 @@
  }
  
  static int
-@@ -617,34 +1602,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
+@@ -617,34 +1621,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
  	tx_cont->tx_ant = td->tx_antenna_mask;
  	tx_cont->band = band;
  
@@ -1864,7 +1893,7 @@
  
  	if (!en) {
  		req.op.rf.param.func_data = cpu_to_le32(band);
-@@ -728,6 +1686,12 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
+@@ -728,6 +1705,12 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
  		mt7915_tm_set_freq_offset(phy, en, en ? td->freq_offset : 0);
  	if (changed & BIT(TM_CHANGED_TXPOWER))
  		mt7915_tm_set_tx_power(phy);
@@ -1877,7 +1906,7 @@
  }
  
  static int
-@@ -737,6 +1701,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -737,6 +1720,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  	struct mt7915_phy *phy = mphy->priv;
  	enum mt76_testmode_state prev_state = td->state;
  
@@ -1889,7 +1918,53 @@
  	mphy->test.state = state;
  
  	if (prev_state == MT76_TM_STATE_TX_FRAMES ||
-@@ -807,6 +1776,7 @@ static int
+@@ -757,7 +1745,7 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ 	    (state == MT76_TM_STATE_OFF &&
+ 	     prev_state == MT76_TM_STATE_IDLE)) {
+ 		u32 changed = 0;
+-		int i;
++		int i, ret;
+ 
+ 		for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
+ 			u16 cur = tm_change_map[i];
+@@ -766,6 +1754,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ 				changed |= BIT(i);
+ 		}
+ 
++		ret = mt7915_tm_check_antenna(phy);
++		if (ret)
++			return ret;
++
+ 		mt7915_tm_update_params(phy, changed);
+ 	}
+ 
+@@ -778,10 +1770,8 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
+ {
+ 	struct mt76_testmode_data *td = &mphy->test;
+ 	struct mt7915_phy *phy = mphy->priv;
+-	struct mt7915_dev *dev = phy->dev;
+-	u32 chainmask = mphy->chainmask, changed = 0;
+-	bool ext_phy = phy != &dev->phy;
+-	int i;
++	u32 changed = 0;
++	int i, ret;
+ 
+ 	BUILD_BUG_ON(NUM_TM_CHANGED >= 32);
+ 
+@@ -789,9 +1779,9 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
+ 	    td->state == MT76_TM_STATE_OFF)
+ 		return 0;
+ 
+-	chainmask = ext_phy ? chainmask >> dev->chainshift : chainmask;
+-	if (td->tx_antenna_mask > chainmask)
+-		return -EINVAL;
++	ret = mt7915_tm_check_antenna(phy);
++	if (ret)
++		return ret;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
+ 		if (tb[tm_change_map[i]])
+@@ -807,6 +1797,7 @@ static int
  mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  {
  	struct mt7915_phy *phy = mphy->priv;
@@ -1897,7 +1972,7 @@
  	void *rx, *rssi;
  	int i;
  
-@@ -852,11 +1822,75 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
+@@ -852,11 +1843,75 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  
  	nla_nest_end(msg, rx);
  
@@ -1974,7 +2049,7 @@
 +	.set_eeprom = mt7915_tm_set_eeprom,
  };
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index a1c54c8..01b08e9 100644
+index a1c54c8..eb0e043 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -4,6 +4,8 @@
@@ -2121,12 +2196,12 @@
 +/* Common Config */
 +/* #define MURU_COMM_PPDU_FMT		BIT(0) */
 +/* #define MURU_COMM_SCH_TYPE		BIT(1) */
-+/* #define MURU_COMM_BAND			BIT(2) */
-+/* #define MURU_COMM_WMM			BIT(3) */
++/* #define MURU_COMM_BAND		BIT(2) */
++/* #define MURU_COMM_WMM		BIT(3) */
 +/* #define MURU_COMM_SPE_IDX		BIT(4) */
 +/* #define MURU_COMM_PROC_TYPE		BIT(5) */
 +/* #define MURU_COMM_SET		(MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \ */
-+/* 				 MURU_COMM_WMM | MURU_COMM_SPE_IDX) */
++/*					 MURU_COMM_WMM | MURU_COMM_SPE_IDX) */
 +/* DL Config */
 +#define MURU_DL_BW			BIT(0)
 +#define MURU_DL_GI			BIT(1)
@@ -2289,7 +2364,7 @@
 +
  #endif
 diff --git a/testmode.c b/testmode.c
-index 1d0d5d3..fd3b9b2 100644
+index 1d0d5d3..97f65fd 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -27,28 +27,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -2340,8 +2415,8 @@
  		td->tx_queued++;
 +
 +		if (td->tx_rate_mode != MT76_TM_TX_MODE_HE_MU)
-+		    if (td->tx_queued - td->tx_done >= limit)
-+			    break;
++			if (td->tx_queued - td->tx_done >= limit)
++				break;
  	}
  
  	dev->queue_ops->kick(dev, q);
@@ -2368,7 +2443,7 @@
 +		q = phy->q_tx[qid];
 +		spin_lock_bh(&q->lock);
 +		mt76_testmode_queue_tx(phy, &phy->dev->global_wcid,
-+				td->tx_skb, q, qid, tx_queued_limit);
++				       td->tx_skb, q, qid, tx_queued_limit);
 +		spin_unlock_bh(&q->lock);
 +
 +		return;
@@ -2387,7 +2462,7 @@
 +
 +	mt76_testmode_queue_tx(phy, td->cur_entry, ed->tx_skb, q, qid, tx_queued_limit);
 +
-+	if (td->tx_pending % td->tx_count == 0 || is_mu)
++	if ((td->tx_count != UINT_MAX && td->tx_pending % td->tx_count == 0) || is_mu)
 +		td->cur_entry = list_next_entry(td->cur_entry, list);
  
  	spin_unlock_bh(&q->lock);
@@ -2686,7 +2761,7 @@
 +
 +		if (!tb[MT76_TM_ATTR_TXBF_PARAM] ||
 +		    mt76_tm_get_u8(tb[MT76_TM_ATTR_TXBF_ACT], &td->txbf_act,
-+		    0, MT76_TM_TXBF_ACT_MAX))
++				   0, MT76_TM_TXBF_ACT_MAX))
 +			goto out;
 +
 +		memset(td->txbf_param, 0, sizeof(td->txbf_param));
@@ -2743,10 +2818,14 @@
  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
-@@ -643,6 +824,15 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
- 	     nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
- 		goto out;
- 
+@@ -640,7 +821,16 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
+ 	     nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
+ 	    (mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&
+-	     nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
++	     nla_put_u32(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
++		goto out;
++
 +	if (nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, ed->tx_mpdu_len) ||
 +	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, ed->tx_rate_nss) ||
 +	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, ed->tx_rate_idx) ||
@@ -2754,13 +2833,11 @@
 +	    nla_put_u8(msg, MT76_TM_ATTR_AID, ed->aid) ||
 +	    nla_put_u8(msg, MT76_TM_ATTR_RU_ALLOC, ed->ru_alloc) ||
 +	    nla_put_u8(msg, MT76_TM_ATTR_RU_IDX, ed->ru_idx))
-+		goto out;
-+
+ 		goto out;
+ 
  	if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
- 		a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
- 		if (!a)
 diff --git a/testmode.h b/testmode.h
-index 8961326..57949f2 100644
+index 8961326..8c55fa0 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -6,6 +6,8 @@
@@ -2778,10 +2855,10 @@
   * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
 + *
 + * @MT76_TM_ATTR_EEPROM_ACTION: eeprom setting actions
-+ * 	(u8, see &enum mt76_testmode_eeprom_action)
++ *	(u8, see &enum mt76_testmode_eeprom_action)
 + * @MT76_TM_ATTR_EEPROM_OFFSET: offset of eeprom data block for writing (u32)
 + * @MT76_TM_ATTR_EEPROM_VAL: values for writing into a 16-byte data block
-+ * 	(nested, u8 attrs)
++ *	(nested, u8 attrs)
 + *
 + * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg)
 + *
@@ -2814,7 +2891,7 @@
 + * enum mt76_testmode_eeprom_action - eeprom setting actions
 + *
 + * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
-+ * 	eeprom data block
++ *	eeprom data block
 + * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
 + * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
 + */
@@ -2832,7 +2909,7 @@
 + * enum mt76_testmode_cfg - packet tx phy mode
 + *
 + * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
-+ * 	eeprom data block
++ *	eeprom data block
 + * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
 + * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
 + */
diff --git a/recipes-wifi/linux-mt76/files/patches/1011-wifi-mt76-testmode-add-pre-cal-support.patch b/recipes-wifi/linux-mt76/files/patches/1011-wifi-mt76-testmode-add-pre-cal-support.patch
index ac7b121..82e8e7d 100644
--- a/recipes-wifi/linux-mt76/files/patches/1011-wifi-mt76-testmode-add-pre-cal-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1011-wifi-mt76-testmode-add-pre-cal-support.patch
@@ -1,10 +1,9 @@
-From 0b10a07db9b3c9dd93861d71da449c521e228b3e Mon Sep 17 00:00:00 2001
+From b933c76718db1c21ecaaf0cddfa4d598617153ea Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Wed, 31 Aug 2022 20:06:52 +0800
-Subject: [PATCH 1011/1033] wifi: mt76: testmode: add pre-cal support
+Subject: [PATCH 1011/1014] wifi: mt76: testmode: add pre-cal support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Change-Id: Ibfbbc3443de994eeb4daa5e364b0a90f5d7d3bcd
 ---
  eeprom.c          |   6 +-
  mt76.h            |   1 +
@@ -114,7 +113,7 @@
  
  #endif
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index e4ab3e0..abb54eb 100644
+index 5cea513..2a515e3 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -391,6 +391,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -127,7 +126,7 @@
  #endif
  	default:
  		break;
-@@ -2887,7 +2890,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
+@@ -2888,7 +2891,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
  	u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
  	u32 total = MT_EE_CAL_GROUP_SIZE;
  
@@ -136,7 +135,7 @@
  		return 0;
  
  	/*
-@@ -2967,11 +2970,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
+@@ -2968,11 +2971,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
  {
  	struct mt7915_dev *dev = phy->dev;
  	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
@@ -192,7 +191,7 @@
  static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
  {
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index c44f13f..146c4d3 100644
+index 62ef4db..b2d26ff 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -5,6 +5,7 @@
@@ -203,7 +202,7 @@
  
  enum {
  	TM_CHANGED_TXPOWER,
-@@ -1580,18 +1581,16 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
+@@ -1599,18 +1600,16 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
  static int
  mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
  {
@@ -224,7 +223,7 @@
  		.icap_len = 120,
  		.op.rf.func_idx = cpu_to_le32(func_idx),
  	};
-@@ -1676,6 +1675,316 @@ out:
+@@ -1695,6 +1694,316 @@ out:
  				 sizeof(req), true);
  }
  
@@ -541,7 +540,7 @@
  static void
  mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
  {
-@@ -1720,6 +2029,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -1739,6 +2048,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  	else if (prev_state == MT76_TM_STATE_OFF ||
  		 state == MT76_TM_STATE_OFF)
  		mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
@@ -552,7 +551,7 @@
  
  	if ((state == MT76_TM_STATE_IDLE &&
  	     prev_state == MT76_TM_STATE_OFF) ||
-@@ -1888,9 +2201,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
+@@ -1909,9 +2222,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
  	return ret;
  }
  
@@ -667,7 +666,7 @@
 +	.dump_precal = mt7915_tm_dump_precal,
  };
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index 01b08e9..d500987 100644
+index eb0e043..7569826 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -81,6 +81,11 @@ struct tm_tx_cont {
@@ -735,7 +734,7 @@
  	TAM_ARB_OP_MODE_NORMAL = 1,
  	TAM_ARB_OP_MODE_TEST,
 diff --git a/testmode.c b/testmode.c
-index fd3b9b2..b5a919a 100644
+index 97f65fd..21362bd 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -766,6 +766,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
@@ -768,7 +767,7 @@
  
  	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
 diff --git a/testmode.h b/testmode.h
-index 57949f2..34936e5 100644
+index 8c55fa0..109a556 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -19,6 +19,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/1012-wifi-mt76-testmode-add-iBF-command-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1012-wifi-mt76-testmode-add-iBF-command-mode-support.patch
index 5a4d921..fb2113a 100644
--- a/recipes-wifi/linux-mt76/files/patches/1012-wifi-mt76-testmode-add-iBF-command-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1012-wifi-mt76-testmode-add-iBF-command-mode-support.patch
@@ -1,10 +1,9 @@
-From 5537367425c0e52ce5da53612e4aaa1bc756c39f Mon Sep 17 00:00:00 2001
+From e44d59d15e90c11b1466b12ac9401922c11504f6 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 12 Sep 2022 18:16:54 +0800
-Subject: [PATCH 1012/1033] wifi: mt76: testmode: add iBF command mode support
+Subject: [PATCH 1012/1014] wifi: mt76: testmode: add iBF command mode support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Change-Id: I7eea1d6412563f889e5774e787e58ce9eba001bd
 ---
  mt7915/testmode.c | 21 ++++++++++++++-------
  testmode.c        | 41 +++++++++++++++++++++++++++++++++++++++++
@@ -13,10 +12,10 @@
  4 files changed, 85 insertions(+), 7 deletions(-)
 
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 146c4d3..6a18cdb 100644
+index b2d26ff..40a3a06 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
-@@ -701,6 +701,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
+@@ -720,6 +720,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
  	struct ieee80211_vif *vif = phy->monitor_vif;
  	struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
  	u8 pfmu_idx = val[0], nc = val[2], nr;
@@ -24,7 +23,7 @@
  	int ret;
  
  	if (td->tx_antenna_mask == 3)
-@@ -748,7 +749,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
+@@ -767,7 +768,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
  	if (ret)
  		return ret;
  
@@ -33,7 +32,7 @@
  		return mt7915_tm_txbf_apply_tx(phy, 1, false, true, true);
  
  	return 0;
-@@ -775,7 +776,7 @@ mt7915_tm_txbf_phase_cal(struct mt7915_phy *phy, u16 *val)
+@@ -794,7 +795,7 @@ mt7915_tm_txbf_phase_cal(struct mt7915_phy *phy, u16 *val)
  		.group_l_m_n = val[1],
  		.sx2 = val[2],
  		.cal_type = val[3],
@@ -42,7 +41,7 @@
  	};
  	struct mt7915_tm_txbf_phase *phase =
  		(struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
-@@ -814,6 +815,8 @@ int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb)
+@@ -833,6 +834,8 @@ int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb)
  			phase = &phase[cal->group];
  			memcpy(&phase->phase, cal->buf + 16, sizeof(phase->phase));
  			phase->status = cal->status;
@@ -51,7 +50,7 @@
  			break;
  		case IBF_PHASE_CAL_VERIFY:
  		case IBF_PHASE_CAL_VERIFY_INSTRUMENT:
-@@ -865,7 +868,6 @@ mt7915_tm_txbf_profile_update_all(struct mt7915_phy *phy, u16 *val)
+@@ -884,7 +887,6 @@ mt7915_tm_txbf_profile_update_all(struct mt7915_phy *phy, u16 *val)
  	pfmu_data->phi11 = cpu_to_le16(phi11);
  	pfmu_data->phi21 = cpu_to_le16(phi21);
  	pfmu_data->phi31 = cpu_to_le16(phi31);
@@ -59,7 +58,7 @@
  	if (subc_id == 63) {
  		struct mt7915_dev *dev = phy->dev;
  		struct {
-@@ -923,8 +925,8 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
+@@ -942,8 +944,8 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
  	struct mt76_testmode_data *td = &phy->mt76->test;
  	u16 *val = td->txbf_param;
  
@@ -70,7 +69,7 @@
  
  	switch (td->txbf_act) {
  	case MT76_TM_TXBF_ACT_INIT:
-@@ -942,10 +944,17 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
+@@ -961,10 +963,17 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
  		return mt7915_tm_txbf_profile_update(phy, val, true);
  	case MT76_TM_TXBF_ACT_PHASE_CAL:
  		return mt7915_tm_txbf_phase_cal(phy, val);
@@ -88,7 +87,7 @@
  	default:
  		break;
  	};
-@@ -1072,7 +1081,6 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
+@@ -1091,7 +1100,6 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
  		rate.legacy = sband->bitrates[rate.mcs].bitrate;
  		break;
  	case MT76_TM_TX_MODE_HT:
@@ -96,7 +95,7 @@
  		flags |= RATE_INFO_FLAGS_MCS;
  
  		if (td->tx_rate_sgi)
-@@ -1437,7 +1445,6 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
+@@ -1456,7 +1464,6 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
  			if (duty_cycle < 100)
  				tx_time = duty_cycle * ipg / (100 - duty_cycle);
  		}
@@ -105,7 +104,7 @@
  		mt7915_tm_set_tx_len(phy, tx_time);
  
 diff --git a/testmode.c b/testmode.c
-index b5a919a..f1982ac 100644
+index 21362bd..39cacb2 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -533,6 +533,42 @@ out:
@@ -152,7 +151,7 @@
  		      void *data, int len)
  {
 @@ -671,6 +707,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- 		    0, MT76_TM_TXBF_ACT_MAX))
+ 				   0, MT76_TM_TXBF_ACT_MAX))
  			goto out;
  
 +		if (td->txbf_act == MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD) {
@@ -164,7 +163,7 @@
  		nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
  			if (nla_len(cur) != 2 ||
 diff --git a/testmode.h b/testmode.h
-index 34936e5..bbfb313 100644
+index 109a556..d2675dd 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -281,8 +281,10 @@ enum mt76_testmode_txbf_act {
diff --git a/recipes-wifi/linux-mt76/files/patches/1013-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1013-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch
index 164b46a..f920fd6 100644
--- a/recipes-wifi/linux-mt76/files/patches/1013-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1013-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch
@@ -1,22 +1,21 @@
-From 32e4319f0e34cb0a1ebb2dbb45c6561a96196a52 Mon Sep 17 00:00:00 2001
+From ee654a359005c8f5e48cc34a42dc76a6550d7e7f Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 27 Oct 2022 17:42:07 +0800
-Subject: [PATCH 1013/1033] wifi: mt76: testmode: add ZWDFS test mode support
+Subject: [PATCH 1013/1014] wifi: mt76: testmode: add ZWDFS test mode support
 
-Change-Id: I14d104b7158a35acf6b0595357d07fb87f5a9d94
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  mt76.h            |   9 ++
  mt76_connac_mcu.h |   2 +
- mt7915/mcu.c      |  66 +++++++++++++
- mt7915/mcu.h      |  46 +++++++++
+ mt7915/mcu.c      |  66 +++++++++++
+ mt7915/mcu.h      |  46 ++++++++
  mt7915/mt7915.h   |   4 +
  mt7915/regs.h     |   2 +
- mt7915/testmode.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
- testmode.c        |  25 ++++-
- testmode.h        |  45 +++++++++
- tools/fields.c    |  22 +++++
- 10 files changed, 452 insertions(+), 1 deletion(-)
+ mt7915/testmode.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++
+ testmode.c        |  25 +++-
+ testmode.h        |  45 ++++++++
+ tools/fields.c    |  22 ++++
+ 10 files changed, 508 insertions(+), 1 deletion(-)
 
 diff --git a/mt76.h b/mt76.h
 index c632852..f4412a2 100644
@@ -59,7 +58,7 @@
  
  enum {
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index abb54eb..2432e57 100644
+index 2a515e3..cb70af5 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -2619,6 +2619,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
@@ -70,7 +69,7 @@
  		req.band_idx = phy->mt76->band_idx;
  		req.scan_mode = 2;
  		break;
-@@ -4601,3 +4602,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
+@@ -4602,3 +4603,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
  	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true);
  }
  #endif
@@ -219,7 +218,7 @@
  int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir);
  int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp);
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index 0339d4b..0798b08 100644
+index b6f36f5..a7e8598 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -1205,6 +1205,8 @@ enum offs_rev {
@@ -232,7 +231,7 @@
  #define MT_WF_PHY_BASE			0x83080000
  #define MT_WF_PHY(ofs)			(MT_WF_PHY_BASE + (ofs))
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 6a18cdb..09b0e98 100644
+index 40a3a06..b98aaaa 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -13,6 +13,12 @@ enum {
@@ -261,12 +260,53 @@
  };
  
  struct reg_band {
-@@ -962,6 +974,216 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
+@@ -981,6 +993,272 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
  	return 0;
  }
  
++static u8
++mt7915_tm_get_center_chan(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef,
++			  int width_mhz)
++{
++	struct mt76_phy *mphy = phy->mt76;
++	const struct ieee80211_channel *chan = mphy->sband_5g.sband.channels;
++	u32 bitmap, i, offset, size = 32;
++	u16 first_control = 0, control_chan = chandef->chan->hw_value;
++	static const u32 width_to_bitmap[] = {
++		[NL80211_CHAN_WIDTH_20_NOHT] = 0x0,
++		[NL80211_CHAN_WIDTH_20] = 0x0,
++		[NL80211_CHAN_WIDTH_40] = 0x55554055,
++		[NL80211_CHAN_WIDTH_80] = 0x44444011,
++		[NL80211_CHAN_WIDTH_80P80] = 0x0,
++		[NL80211_CHAN_WIDTH_160] = 0x04004001,
++	};
++
++	bitmap = width_to_bitmap[chandef->width];
++	if (!bitmap)
++		return control_chan;
++
++	offset = width_mhz / 10 - 2;
++	for (i = 0; i < size; i++) {
++		if (!((1 << i) & bitmap))
++			continue;
++
++		if (control_chan >= chan[i].hw_value)
++			first_control = chan[i].hw_value;
++		else
++			break;
++	}
++
++	if (chandef->width == NL80211_CHAN_WIDTH_40 &&
++	    control_chan >= chan[size].hw_value)
++		return chan[size].hw_value + offset;
++	else if (first_control == 0)
++		return control_chan;
++
++	return first_control + offset;
++}
++
 +static int
-+mt7915_tm_set_offchan(struct mt7915_phy *phy)
++mt7915_tm_set_offchan(struct mt7915_phy *phy, bool no_center)
 +{
 +	struct mt76_phy *mphy = phy->mt76;
 +	struct mt7915_dev *dev = phy->dev;
@@ -293,10 +333,24 @@
 +
 +	chandef.width = td->offchan_bw;
 +	width_mhz = bw_to_mhz[chandef.width];
-+	chandef.center_freq1 = freq;
 +	chan = ieee80211_get_channel(hw->wiphy, freq);
++	if (!chan) {
++		ret = -EINVAL;
++		dev_info(dev->mt76.dev, "Failed to set offchan (invalid control channel)!\n");
++		goto out;
++	}
 +	chandef.chan = chan;
 +
++	if (no_center)
++		td->offchan_center_ch = mt7915_tm_get_center_chan(phy, &chandef, width_mhz);
++	chandef.center_freq1 = ieee80211_channel_to_frequency(td->offchan_center_ch,
++							      NL80211_BAND_5GHZ);
++	if (!cfg80211_chandef_valid(&chandef)) {
++		ret = -EINVAL;
++		dev_info(dev->mt76.dev, "Failed to set offchan, chandef is invalid!\n");
++		goto out;
++	}
++
 +	memset(&dev->rdd2_chandef, 0, sizeof(struct cfg80211_chan_def));
 +
 +	ret = mt7915_mcu_rdd_background_enable(phy, &chandef);
@@ -311,6 +365,7 @@
 +
 +out:
 +	td->offchan_ch = 0;
++	td->offchan_center_ch = 0;
 +	td->offchan_bw = 0;
 +
 +	return ret;
@@ -478,7 +533,7 @@
  static int
  mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min,
  		      u16 cw_max, u16 txop, u8 tx_cmd)
-@@ -1249,6 +1471,8 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
+@@ -1268,6 +1546,8 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
  		phy->mt76->test.tx_mpdu_len = 0;
  		phy->test.bf_en = 0;
  		mt7915_tm_set_entry(phy);
@@ -487,13 +542,13 @@
  	}
  }
  
-@@ -2008,6 +2232,14 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
+@@ -2027,6 +2307,14 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
  		mt7915_tm_set_cfg(phy);
  	if (changed & BIT(TM_CHANGED_TXBF_ACT))
  		mt7915_tm_set_txbf(phy);
 +	if ((changed & BIT(TM_CHANGED_OFF_CHAN_CH)) &&
 +	    (changed & BIT(TM_CHANGED_OFF_CHAN_BW)))
-+		mt7915_tm_set_offchan(phy);
++		mt7915_tm_set_offchan(phy, !(changed & BIT(TM_CHANGED_OFF_CHAN_CENTER_CH)));
 +	if ((changed & BIT(TM_CHANGED_IPI_THRESHOLD)) &&
 +	    (changed & BIT(TM_CHANGED_IPI_PERIOD)))
 +		mt7915_tm_set_ipi(phy);
@@ -503,7 +558,7 @@
  
  static int
 diff --git a/testmode.c b/testmode.c
-index f1982ac..503d714 100644
+index 39cacb2..293ad98 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -24,6 +24,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -567,11 +622,11 @@
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
 diff --git a/testmode.h b/testmode.h
-index bbfb313..e03fa6d 100644
+index d2675dd..97e7596 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -63,6 +63,20 @@
-  * 	(nested, u8 attrs)
+  *	(nested, u8 attrs)
   *
   * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg)
 + * @MT76_TM_ATTR_TXBF_ACT: txbf setting actions (u8)
diff --git a/recipes-wifi/linux-mt76/files/patches/1014-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch b/recipes-wifi/linux-mt76/files/patches/1014-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch
index 3ae285a..1163a02 100644
--- a/recipes-wifi/linux-mt76/files/patches/1014-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1014-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch
@@ -1,4 +1,4 @@
-From 4340e9c467389c104e62d7cd060a5494d83f24bf Mon Sep 17 00:00:00 2001
+From 44b3c5fed9a9c63e7da34004d265669f241a2886 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 15 Dec 2022 19:45:18 +0800
 Subject: [PATCH] wifi: mt76: testmode: add iBF/eBF cal and cert commands with
@@ -836,7 +836,7 @@
 +}
 +#endif
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index 0d90251e..a0d5324b 100644
+index a7e8598..5d91b80 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -61,6 +61,7 @@ enum offs_rev {
@@ -858,7 +858,7 @@
  #define MT_WF_RMAC_BASE(_band)		((_band) ? 0x820f5000 : 0x820e5000)
  #define MT_WF_RMAC(_band, ofs)		(MT_WF_RMAC_BASE(_band) + (ofs))
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 09b0e98e..b99bed54 100644
+index b98aaaa..5665da7 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -53,6 +53,8 @@ struct reg_band {
@@ -1491,7 +1491,7 @@
  
 -	pr_info("ibf cal process: act = %u, val = %u, %u, %u, %u, %u, %u\n",
 -		td->txbf_act, val[0], val[1], val[2], val[3], val[4], val[5]);
-+	dev_info(phy->dev->mt76.dev, "ibf cal process: act = %u, val = %u, %u, %u, %u, %u, %u\n",
++	dev_info(phy->dev->mt76.dev, "ibf cal process: act = %u, val = %u, %u, %u, %u, %u, %u, %u\n",
 +		 td->txbf_act, val[0], val[1], val[2], val[3], val[4], val[5], val[6]);
  
  	switch (td->txbf_act) {
@@ -1701,7 +1701,7 @@
  	rateval =  mode << 6 | rate_idx;
  	tx_cont->rateval = cpu_to_le16(rateval);
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index d500987d..19823694 100644
+index 7569826..5aba13c 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -311,137 +311,7 @@ struct mt7915_tm_muru {
@@ -1845,7 +1845,7 @@
  
  #endif
 diff --git a/testmode.c b/testmode.c
-index 503d714b..91638083 100644
+index 293ad98..f16c6ea 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -194,6 +194,7 @@ mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len,
@@ -1857,7 +1857,7 @@
  	memcpy(hdr->addr2, addr[1], ETH_ALEN);
  	memcpy(hdr->addr3, addr[2], ETH_ALEN);
 diff --git a/testmode.h b/testmode.h
-index e03fa6df..0e96173b 100644
+index 97e7596..e13920e 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -299,7 +299,10 @@ enum mt76_testmode_cfg {
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_dsp.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_dsp.bin
index d5d541f..1c7710b 100755
--- a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_dsp.bin
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_dsp.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_rom_patch.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_rom_patch.bin
index 8a02116..7b151c9 100644
--- a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_rom_patch.bin
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_rom_patch.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wa.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wa.bin
index 924509d..b0433e8 100644
--- a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wa.bin
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wa.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm.bin
index 5bbf475..7188830 100644
--- a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm.bin
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm_tm.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm_tm.bin
index 8f91f29..9ddee02 100644
--- a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm_tm.bin
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_wm_tm.bin
Binary files differ
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/432-missing-typedef.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/432-missing-typedef.patch
deleted file mode 100644
index 7a100f1..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/432-missing-typedef.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/src/drivers/linux_wext.h
-+++ b/src/drivers/linux_wext.h
-@@ -26,6 +26,7 @@ typedef int32_t __s32;
- typedef uint16_t __u16;
- typedef int16_t __s16;
- typedef uint8_t __u8;
-+typedef int8_t __s8;
- #ifndef __user
- #define __user
- #endif /* __user */
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
index a79555a..0892d3f 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
@@ -1,7 +1,7 @@
-From fd2df638591cc86c21153e94abe8fc00451703b8 Mon Sep 17 00:00:00 2001
+From ee34d2ccb27863f0eaa7abb0f65477ab9a0dd92f Mon Sep 17 00:00:00 2001
 From: TomLiu <tomml.liu@mediatek.com>
 Date: Tue, 9 Aug 2022 10:23:44 -0700
-Subject: [PATCH 06/28] hostapd: mtk: Add hostapd MU SET/GET control
+Subject: [PATCH 06/32] hostapd: mtk: Add hostapd MU SET/GET control
 
 ---
  hostapd/config_file.c             |   9 +++
@@ -156,14 +156,14 @@
  	{ "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL,
  	  "report a scanned DPP URI from a QR Code" },
 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 55c35c7..1cad303 100644
+index 55c35c7..afa19ec 100644
 --- a/src/ap/ap_config.c
 +++ b/src/ap/ap_config.c
 @@ -280,6 +280,7 @@ struct hostapd_config * hostapd_config_defaults(void)
  	conf->he_6ghz_max_ampdu_len_exp = 7;
  	conf->he_6ghz_rx_ant_pat = 1;
  	conf->he_6ghz_tx_ant_pat = 1;
-+	conf->mu_onoff = 13;
++	conf->mu_onoff = 15;
  #endif /* CONFIG_IEEE80211AX */
  
  	/* The third octet of the country string uses an ASCII space character
@@ -446,5 +446,5 @@
  			}
  
 -- 
-2.18.0
+2.39.0
 
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
index c53b55a..bf91686 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -1,19 +1,18 @@
-From 3237a993233da052219018eec10ca82d79225fdb Mon Sep 17 00:00:00 2001
+From 705e1a59381e7bbd92043ad4338834aad504f232 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 20 Feb 2023 16:58:20 +0800
-Subject: [PATCH 18/28] hostapd: mtk: Fix auto ht issue when switching to DFS
- channel
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- hostapd/ctrl_iface.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
+ hostapd/ctrl_iface.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
 
 diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 07de0ad..be86f6c 100644
+index 07de0ad..3c38df5 100644
 --- a/hostapd/ctrl_iface.c
 +++ b/hostapd/ctrl_iface.c
-@@ -2773,6 +2773,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2773,6 +2773,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		break;
  	}
  
@@ -21,12 +20,13 @@
 +		settings.freq_params.ht_enabled = iface->conf->ieee80211n;
 +		settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
 +		settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++		settings.freq_params.eht_enabled = iface->conf->ieee80211be;
 +	}
 +
  	if (settings.freq_params.center_freq1)
  		dfs_range += hostapd_is_dfs_overlap(
  			iface, bandwidth, settings.freq_params.center_freq1);
-@@ -2810,12 +2816,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2810,12 +2817,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		return 0;
  	}
  
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
similarity index 88%
rename from recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
rename to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
index 9b46d70..e4667e4 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0029-hostapd-mtk-Fix-CCA-issue.patch
@@ -1,12 +1,12 @@
-From 39a0dd44653f12ce13af68de81bfae683669623a Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Thu, 11 May 2023 14:08:59 +0800
-Subject: [PATCH 101/103] hostapd: mtk: Fix CCA issue
+From c92a1e50abdad2bf3e961c9d5aa34baea81f025b Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 3 May 2023 14:55:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix CCA issue
 
-When receiving CCA related nl80211 command, hostapd used to work on
+When receiving CCA-related nl80211 commands, hostapd used to work on
 struct wpa_driver_nl80211_data, whose ctx always points to
-hostpad_iface->bss[0]. However, CCA command is sent on per-BSS based.
-This patch makes hostapd handle CCA related commands on per-BSS based.
+hostpad_iface->bss[0]. However, CCA commands are sent on a per-BSS based.
+This patch makes hostapd handle CCA-related commands on a per-BSS based.
 
 Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
 ---
@@ -93,5 +93,5 @@
  #endif /* CONFIG_IEEE80211AX */
  	default:
 -- 
-2.18.0
+2.25.1
 
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
similarity index 66%
rename from recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
rename to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
index 4075531..f9c4714 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
@@ -1,15 +1,14 @@
-From 097b204ffed838a4bbf7649fb23310f64ace22ad Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Thu, 11 May 2023 14:12:44 +0800
-Subject: [PATCH 102/103] hostapd: mtk: Fix unexpected AP beacon state
- transition
+From c4d3890bbf1bd8c8ac8bfaa56fd16e2391e05181 Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 3 May 2023 16:10:57 +0800
+Subject: [PATCH] hostapd: mtk: Fix unexpected AP beacon state transition
 
-When AP fails setting the beacon, it assigns bss->beacon_set to 0 no
+When AP fails to set the beacon, it assigns bss->beacon_set to 0 no
 matter what the error number is.
 However, in the case that the error number is -EBUSY, the driver might
 not free the beacon and expect a later beacon re-setting. If hostapd set
-a new beacon under this case, driver will return -EALREADY.
-This patch checks the error number after hostapd fails setting the
+a new beacon under this case, the driver will return -EALREADY.
+This patch checks the error number after hostapd fails to set the
 beacon. If the error number is -EBUSY, bss->beacon_set will not be
 assigned to 0.
 
@@ -19,7 +18,7 @@
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 8400e57..ccfc2d0 100644
+index 8400e57..5013207 100644
 --- a/src/drivers/driver_nl80211.c
 +++ b/src/drivers/driver_nl80211.c
 @@ -5126,7 +5126,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
@@ -33,5 +32,5 @@
  		bss->flink->beacon_set = 1;
  		nl80211_set_bss(bss, params->cts_protect, params->preamble,
 -- 
-2.18.0
+2.25.1
 
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch
new file mode 100644
index 0000000..1c5cacc
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch
@@ -0,0 +1,53 @@
+From 43c8934074a4f6fd1e98143b3bd011e71fe69fdb Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Fri Jun 9 09:03:05 2023 +0800
+Subject: hostapd: mtk: Add HE capabilities check
+
+Add HE capabilities check.
+Since "HE capabilities" check has been removed by driver,
+add the support for "HE capabilities" check in hostapd.
+
+---
+ src/ap/hw_features.c         | 26 ++++++++++++++++++++++++++
+ 1 files changed, 26 insertions(+)
+
+diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
+index 9967494..309f2d5 100644
+--- a/src/ap/hw_features.c
++++ b/src/ap/hw_features.c
+@@ -680,6 +680,32 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
+ #ifdef CONFIG_IEEE80211AX
+ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
+ {
++	struct hostapd_hw_modes *mode = iface->current_mode;
++	struct he_capabilities *he_cap = &mode->he_capab[IEEE80211_MODE_AP];
++	struct hostapd_config *conf = iface->conf;
++
++#define HE_CAP_CHECK(hw_cap, field, phy_idx, cfg_cap)					\
++	do {									\
++		if (cfg_cap && !(hw_cap[phy_idx] & field)) {	\
++			wpa_printf(MSG_ERROR, "Driver does not support configured" \
++				     " HE capability [%s]", #field);		\
++			return 0;						\
++		}								\
++	} while (0)
++
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_LDPC_CODING_IN_PAYLOAD,
++		     HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX,
++		     conf->he_phy_capab.he_ldpc);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_SU_BEAMFORMER_CAPAB,
++		     HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX,
++		     conf->he_phy_capab.he_su_beamformer);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_SU_BEAMFORMEE_CAPAB,
++		     HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX,
++		     conf->he_phy_capab.he_su_beamformee);
++	HE_CAP_CHECK(he_cap->phy_cap, HE_PHYCAP_MU_BEAMFORMER_CAPAB,
++		     HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX,
++		     conf->he_phy_capab.he_mu_beamformer);
++
+ 	return 1;
+ }
+ #endif /* CONFIG_IEEE80211AX */
+-- 
+2.39.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch
new file mode 100644
index 0000000..01a134e
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch
@@ -0,0 +1,44 @@
+From 0aaec4ebc72e40da76a279d817763f4655f45d21 Mon Sep 17 00:00:00 2001
+From: mtk23510 <rudra.shahi@mediatek.com>
+Date: Fri, 26 May 2023 14:52:35 +0800
+Subject: [PATCH] hostapd: mtk: Add support for gtk rekeying in hostapd cli
+
+Signed-off-by: mtk23510 <rudra.shahi@mediatek.com>
+---
+ hostapd/hostapd_cli.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 02f8546..d529bbc 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1256,6 +1256,15 @@ static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
+ }
+ 
+ 
++#ifdef CONFIG_TESTING_OPTIONS
++static int hostapd_cli_cmd_rekey_gtk(struct wpa_ctrl *ctrl, int argc,
++				      char *argv[])
++{
++	return wpa_ctrl_command(ctrl, "REKEY_GTK");
++}
++#endif
++
++
+ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+ 	char cmd[256];
+@@ -1761,6 +1770,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ 	  "= disable hostapd on current interface" },
+ 	{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
+ 	  "= update Beacon frame contents\n"},
++#ifdef CONFIG_TESTING_OPTIONS
++	{ "rekey_gtk", hostapd_cli_cmd_rekey_gtk, NULL,
++	  "= rekey gtk\n"},
++#endif
+ 	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
+ 	  "= drop all ERP keys"},
+ 	{ "log_level", hostapd_cli_cmd_log_level, NULL,
+-- 
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
index a71c43f..a0c06b1 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
@@ -36,7 +36,6 @@
     file://420-indicate-features.patch \
     file://430-hostapd_cli_ifdef.patch \
     file://431-wpa_cli_ifdef.patch \
-    file://432-missing-typedef.patch \
     file://450-scan_wait.patch;apply=no \
     file://460-wpa_supplicant-add-new-config-params-to-be-used-with.patch \
     file://463-add-mcast_rate-to-11s.patch \
@@ -87,8 +86,10 @@
     file://mtk-0026-hostapd-mtk-avoid-setting-beacon-after-wpa_supplican.patch \
     file://mtk-0027-hostapd-mtk-Fix-setting-wrong-seg0-index-for-5G-cent.patch \
     file://mtk-0028-hostapd-mtk-Add-muru-user-number-debug-command.patch \
+    file://mtk-0029-hostapd-mtk-Fix-CCA-issue.patch \
+    file://mtk-0030-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch \
+    file://mtk-0032-hostapd-mtk-Add-HE-capabilities-check.patch \
     file://mtk-0100-hostapd-mtk-update-eht-operation-element.patch \
-    file://mtk-0101-hostapd-mtk-Fix-CCA-issue.patch \
-    file://mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch \
     file://mtk-0103-hostapd-mtk-Add-BW320-channel-switch-command.patch \
+    file://mtk-0104-hostapd-mtk-Add-support-for-gtk-rekeying-in-hostapd-.patch \
     "
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
index f89da87..d5f0dac 100644
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -1,19 +1,18 @@
-From 0aa1200534c41279f5f05e1919040a86f003ca0a Mon Sep 17 00:00:00 2001
+From a71a78bc51b74d331aeb3f900c03480d058d5233 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 20 Feb 2023 16:58:20 +0800
-Subject: [PATCH 19/29] hostapd: mtk: Fix auto ht issue when switching to DFS
- channel
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- hostapd/ctrl_iface.c | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
 
 diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 61c9e80..06cbea1 100644
+index 61c9e80..c33b7a4 100644
 --- a/hostapd/ctrl_iface.c
 +++ b/hostapd/ctrl_iface.c
-@@ -2698,6 +2698,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		break;
  	}
  
@@ -21,13 +20,12 @@
 +		settings.freq_params.ht_enabled = iface->conf->ieee80211n;
 +		settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
 +		settings.freq_params.he_enabled = iface->conf->ieee80211ax;
-+		settings.freq_params.eht_enabled = iface->conf->ieee80211be;
 +	}
 +
  	if (settings.freq_params.center_freq1)
  		dfs_range += hostapd_is_dfs_overlap(
  			iface, bandwidth, settings.freq_params.center_freq1);
-@@ -2735,12 +2742,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
  		return 0;
  	}