[rdkb][common][bsp][Refactor and sync kernel from openwrt]

[Description]
935871e8 [kernel][mt7988][PMIC][Fix missing cpu frequency and PMIC devicetree nodes]
90c699e8 [kernel][common][eth][Fix issues detected by Coverity scan]
e008f4d9 [openwrt][mt7988][crypto][Fix eip driver coverity]
a5ea5dca [kernel][common][hnat][Refactor PPPQ to dispatch ACK packets to the high priority TXQ]
8e417d1f [openwrt][mt7988][crypto][Refactor kernel patch to decouple IPSec and hnat]
356faafe [openwrt][mt7988][crypto][Refactor to unify EIP driver]
af9caf1b [CRITICAL][kernel][common][eth][Fix SW path transmission timeout issue]
58eeb898 [HIGH][kernel][common][eth][Update Airoha EN8811H 2.5G PHY driver to v1.2.5]
5f29c7ff [openwrt][mt7988][crypto][Add scatterlist API in DDK for look-aside mode]
bead1a2b [openwrt][mt7988][crypto][Add look-aside mode]
d1ca477e [openvswitch][common][Fix IPv6 client can't get RA packet]
656dd84a [kernel][mt7981][eth][Add DTS for the SFP]
e6acedf7 [kernel][common][hnat][Fix issues detected by Coverity scan]
a04d0886 [kernel][common][eth][Fix issues detected by Coverity scan]
84c95b0a [openwrt][common][app][Fix switch issues detected by Coverity]
7012eb9f [openwrt][common][Upgrade kernel version from 5.4.260 to 5.4.271]
186c1407 [kernel][common][eth][Fix issues detected by Coverity scan]
eb29f0ec [kernel][mt7988][eth][Enhance the TX performance of the QDMA]
ee6f32a9 [CRITICAL][kernel][mt7988][eth][Fix issue of transmitting abnormal data for USXGMII]
9433a462 [MAC80211][WED][Add kite two pcie with two wed support]

[Release-log]

Change-Id: I9184720254bbcd9a9ed159afcb20e86a29c3b0d6
diff --git a/recipes-devtools/switch/files/src/switch_fun.c b/recipes-devtools/switch/files/src/switch_fun.c
index 9e9f4fe..e439ee8 100644
--- a/recipes-devtools/switch/files/src/switch_fun.c
+++ b/recipes-devtools/switch/files/src/switch_fun.c
@@ -11,6 +11,7 @@
 #include <linux/if.h>
 #include <stdbool.h>
 #include <time.h>
+#include <errno.h>
 
 #include "switch_extend.h"
 #include "switch_netlink.h"
@@ -3236,10 +3237,37 @@
 void ingress_rate_set(int argc, char *argv[])
 {
 	int on_off = 0, port = 0, bw = 0;
+	char *endptr;
 
-	port = strtoul(argv[3], NULL, 0);
+	/* clear errno before conversion to detect overflow */
+	errno = 0;
+	port = strtoul(argv[3], &endptr, 0);
+
+	if (errno == ERANGE) {
+		printf("Conversion error, value out of range\n");
+		return;
+	}
+	if (*endptr != '\0') {
+		printf("Conversion error, no digits were found\n");
+		return;
+	}
+
+	if (port < 0 || port > 6) {
+		printf("Wrong port range, should be within 0-6\n");
+		return;
+	}
+
 	if (argv[2][1] == 'n') {
-		bw = strtoul(argv[4], NULL, 0);
+		errno = 0;
+		bw = strtoul(argv[4], &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Conversion error, value out of range\n");
+			return;
+		}
+		if (*endptr != '\0') {
+			printf("Conversion error, no digits were found\n");
+			return;
+		}
 		on_off = 1;
 	} else if (argv[2][1] == 'f') {
 		if (argc != 4)
@@ -3309,10 +3337,34 @@
 {
 	unsigned int value = 0, reg = 0;
 	int on_off = 0, port = 0, bw = 0;
+	char *endptr;
 
-	port = strtoul(argv[3], NULL, 0);
+	/* clear errno before conversion to detect overflow */
+	errno = 0;
+	port = strtoul(argv[3], &endptr, 0);
+	if (errno == ERANGE) {
+		printf("Conversion error, value out of range\n");
+		return;
+	}
+	if (*endptr != '\0') {
+		printf("Conversion error, no digits were found\n");
+		return;
+	}
+	if (port < 0 || port > 6) {
+		printf("Wrong port range, should be within 0-6\n");
+		return;
+	}
 	if (argv[2][1] == 'n') {
-		bw = strtoul(argv[4], NULL, 0);
+		errno = 0;
+		bw = strtoul(argv[4], &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Conversion error, value out of range\n");
+			return;
+		}
+		if (*endptr != '\0') {
+			printf("Conversion error, no digits were found\n");
+			return;
+		}
 		on_off = 1;
 	} else if (argv[2][1] == 'f') {
 		if (argc != 4)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts
new file mode 100644
index 0000000..e0c1165
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts
@@ -0,0 +1,319 @@
+/dts-v1/;
+#include "mt7981.dtsi"
+/ {
+	model = "MediaTek MT7981 RFB";
+	compatible = "mediatek,mt7981-spim-snand-sfp";
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11002000";
+	};
+
+	memory {
+		// fpga ddr2: 128MB*2
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	gpio-keys {
+			compatible = "gpio-keys";
+				reset {
+					label = "reset";
+					linux,code = <KEY_RESTART>;
+					gpios = <&pio 1 GPIO_ACTIVE_LOW>;
+				};
+
+				wps {
+					label = "wps";
+					linux,code = <KEY_WPS_BUTTON>;
+					gpios = <&pio 0 GPIO_ACTIVE_HIGH>;
+				};
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0200000>;
+			};
+
+			partition@380000 {
+				label = "FIP";
+				reg = <0x380000 0x0200000>;
+			};
+
+			partition@580000 {
+				label = "ubi";
+				reg = <0x580000 0x4000000>;
+			};
+		};
+	};
+
+	sfp_cage1: sfp@1 {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c0>;
+		mod-def0-gpios = <&pio 25 1>;
+		los-gpios = <&pio 28 0>;
+		tx-disable-gpios = <&pio 27 0>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "okay";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "2500base-x";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "2500base-x";
+		managed = "in-band-status";
+		sfp = <&sfp_cage1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reset-gpios = <&pio 14 1>;
+		reset-delay-us = <600>;
+
+		switch@0 {
+			compatible = "mediatek,mt7531";
+			reg = <31>;
+			reset-gpios = <&pio 39 0>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan1";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan2";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan3";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan4";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "2500base-x";
+
+					fixed-link {
+						speed = <2500>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-max-gmac = <2>;
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+
+	slb9670: slb9670@0 {
+		compatible = "infineon,slb9670";
+		reg = <0>; /* CE0 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <2>;
+		spi-cal-data = /bits/ 8 <0x00 0x1b>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
+&wbsys {
+	mediatek,mtd-eeprom = <&factory 0x0000>;
+	status = "okay";
+	pinctrl-names = "dbdc";
+	pinctrl-0 = <&wf_dbdc_pins>;
+};
+
+&pio {
+
+	i2c_pins: i2c-pins-g1 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	pcm_pins: pcm-pins-g0 {
+		mux {
+			function = "pcm";
+			groups = "pcm";
+		};
+	};
+
+	pwm0_pin: pwm0-pin-g0 {
+		mux {
+			function = "pwm";
+			groups = "pwm0_0";
+		};
+	};
+
+	pwm1_pin: pwm1-pin-g0 {
+		mux {
+			function = "pwm";
+			groups = "pwm1_0";
+		};
+	};
+
+	pwm2_pin: pwm2-pin {
+		mux {
+			function = "pwm";
+			groups = "pwm2";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+
+		conf-pu {
+			pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+		};
+
+		conf-pd {
+			pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	uart1_pins: uart1-pins-g1 {
+		mux {
+			function = "uart";
+			groups = "uart1_1";
+		};
+	};
+
+	uart2_pins: uart2-pins-g1 {
+		mux {
+			function = "uart";
+			groups = "uart2_1";
+		};
+	};
+
+	wf_dbdc_pins: wf_dbdc-pins {
+		mux {
+			function = "eth";
+			groups = "wf0_mode1";
+		};
+		conf {
+			pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4",
+			       "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6",
+			       "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10",
+			       "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ",
+			       "WF_CBA_RESETB", "WF_DIG_RESETB";
+			drive-strength = <MTK_DRIVE_4mA>;
+		};
+	};
+};
+
+&xhci {
+	status = "okay";
+};
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 5a12bf9..1fb43e5 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
@@ -63,6 +63,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -137,6 +189,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-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 f175a27..c41aa57 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
@@ -54,6 +54,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -128,6 +180,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-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 a4a61d6..7881834 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
@@ -88,6 +88,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -162,6 +214,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-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 a22af29..2fa9f5d 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
@@ -45,6 +45,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -162,6 +214,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/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 f13573c..2f32e45 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
@@ -67,6 +67,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -148,6 +200,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/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 858c3e0..d7e41c5 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
@@ -58,6 +58,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -139,6 +191,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/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 f7c2338..f3cee2b 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
@@ -92,6 +92,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -173,6 +225,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/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 effcfd8..be66a65 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
@@ -49,6 +49,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -173,6 +225,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/mt7988d-dsa-10g-wan-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
index 508ee7b..71c2e3d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
@@ -67,6 +67,58 @@
 	status = "okay";
 };
 
+&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;
+			};
+		};
+	};
+};
+
 &spi1 {
 	pinctrl-names = "default";
 	/* pin shared with snfi */
@@ -148,6 +200,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/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 f902989..91caa38 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
@@ -887,7 +887,7 @@
 	seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count));
 	seq_printf(seq, "cpu next free: %d\n", (int)(ring->next_free - ring->dma));
 	seq_printf(seq, "cpu last free: %d\n", (int)(ring->last_free - ring->dma));
-	for (i = 0; i < MTK_DMA_SIZE; i++) {
+	for (i = 0; i < eth->soc->txrx.tx_dma_size; i++) {
 		dma_addr_t tmp = ring->phys +
 				 i * (dma_addr_t)eth->soc->txrx.txd_size;
 
@@ -929,7 +929,7 @@
 	struct mtk_tx_dma_v2 *hwtx_ring;
 	int i = 0;
 
-	for (i = 0; i < MTK_DMA_SIZE; i++) {
+	for (i = 0; i < eth->soc->txrx.fq_dma_size; i++) {
 		dma_addr_t addr = eth->phy_scratch_ring +
 				  i * (dma_addr_t)eth->soc->txrx.txd_size;
 
@@ -978,7 +978,7 @@
 			continue;
 
 		seq_printf(seq, "[Ring%d] next to read: %d\n", j,
-			   NEXT_DESP_IDX(ring->calc_idx, MTK_DMA_SIZE));
+			   NEXT_DESP_IDX(ring->calc_idx, eth->soc->txrx.rx_dma_size));
 		for (i = 0; i < ring->dma_size; i++) {
 			rx_ring = ring->dma + i * eth->soc->txrx.rxd_size;
 
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 bd4aac7..126f284 100644
--- 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
@@ -816,9 +816,12 @@
 
 	/* Enable SGMII */
 	if (interface == PHY_INTERFACE_MODE_SGMII ||
-	    phy_interface_mode_is_8023z(interface))
+	    phy_interface_mode_is_8023z(interface)) {
+		spin_lock(&eth->syscfg0_lock);
 		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
 				   SYSCFG0_SGMII_MASK, mac->syscfg0);
+		spin_unlock(&eth->syscfg0_lock);
+	}
 
 	return 0;
 }
@@ -1720,10 +1723,10 @@
 {
 	const struct mtk_soc_data *soc = eth->soc;
 	dma_addr_t phy_ring_tail;
-	int cnt = MTK_DMA_SIZE;
+	int cnt = soc->txrx.fq_dma_size;
 	dma_addr_t dma_addr;
 	u64 addr64 = 0;
-	int i;
+	int i, j, len;
 
 	if (!eth->soc->has_sram) {
 		eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
@@ -1737,40 +1740,44 @@
 	if (unlikely(!eth->scratch_ring))
                         return -ENOMEM;
 
-	eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
-	if (unlikely(!eth->scratch_head))
-		return -ENOMEM;
-
-	dma_addr = dma_map_single(eth->dma_dev,
-				  eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE,
-				  DMA_FROM_DEVICE);
-	if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
-		return -ENOMEM;
-
 	phy_ring_tail = eth->phy_scratch_ring +
 			(dma_addr_t)soc->txrx.txd_size * (cnt - 1);
 
-	for (i = 0; i < cnt; i++) {
-		struct mtk_tx_dma_v2 *txd;
+	for (j = 0; j < DIV_ROUND_UP(soc->txrx.fq_dma_size, MTK_FQ_DMA_LENGTH); j++) {
+		len = min_t(int, cnt - j * MTK_FQ_DMA_LENGTH, MTK_FQ_DMA_LENGTH);
 
-		txd = eth->scratch_ring + i * soc->txrx.txd_size;
-		txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
-		if (i < cnt - 1)
-			txd->txd2 = eth->phy_scratch_ring +
-				(i + 1) * soc->txrx.txd_size;
+		eth->scratch_head[j] = kcalloc(len, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
+		if (unlikely(!eth->scratch_head[j]))
+			return -ENOMEM;
 
-		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
-			  TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
+		dma_addr = dma_map_single(eth->dma_dev,
+					  eth->scratch_head[j], len * MTK_QDMA_PAGE_SIZE,
+					  DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
+			return -ENOMEM;
 
-		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
-		txd->txd4 = 0;
+		for (i = 0; i < len; i++) {
+			struct mtk_tx_dma_v2 *txd;
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
-		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
-			txd->txd5 = 0;
-			txd->txd6 = 0;
-			txd->txd7 = 0;
-			txd->txd8 = 0;
+			txd = eth->scratch_ring + (j * MTK_FQ_DMA_LENGTH + i) * soc->txrx.txd_size;
+			txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
+			if (j * MTK_FQ_DMA_LENGTH + i < cnt)
+				txd->txd2 = eth->phy_scratch_ring +
+					(j * MTK_FQ_DMA_LENGTH + i + 1) * soc->txrx.txd_size;
+
+			addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+				  TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
+
+			txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
+			txd->txd4 = 0;
+
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+			    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+				txd->txd5 = 0;
+				txd->txd6 = 0;
+				txd->txd7 = 0;
+				txd->txd8 = 0;
+			}
 		}
 	}
 
@@ -2799,25 +2806,25 @@
 	int i, sz = soc->txrx.txd_size;
 	struct mtk_tx_dma_v2 *txd, *pdma_txd;
 
-	ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf),
+	ring->buf = kcalloc(soc->txrx.tx_dma_size, sizeof(*ring->buf),
 			       GFP_KERNEL);
 	if (!ring->buf)
 		goto no_tx_mem;
 
 	if (!eth->soc->has_sram)
-		ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
+		ring->dma = dma_alloc_coherent(eth->dma_dev, soc->txrx.tx_dma_size * sz,
 					       &ring->phys, GFP_KERNEL);
 	else {
-		ring->dma =  eth->sram_base + MTK_DMA_SIZE * sz;
+		ring->dma =  eth->sram_base + soc->txrx.fq_dma_size * sz;
 		ring->phys = eth->phy_scratch_ring +
-			     MTK_DMA_SIZE * (dma_addr_t)sz;
+			     soc->txrx.fq_dma_size * (dma_addr_t)sz;
 	}
 
 	if (!ring->dma)
 		goto no_tx_mem;
 
-	for (i = 0; i < MTK_DMA_SIZE; i++) {
-		int next = (i + 1) % MTK_DMA_SIZE;
+	for (i = 0; i < soc->txrx.tx_dma_size; i++) {
+		int next = (i + 1) % soc->txrx.tx_dma_size;
 		u32 next_ptr = ring->phys + next * sz;
 
 		txd = ring->dma + i * sz;
@@ -2840,12 +2847,12 @@
 	 */
 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		ring->dma_pdma = dma_alloc_coherent(eth->dma_dev,
-						    MTK_DMA_SIZE * sz,
+						    soc->txrx.tx_dma_size * sz,
 						    &ring->phys_pdma, GFP_KERNEL);
 		if (!ring->dma_pdma)
 			goto no_tx_mem;
 
-		for (i = 0; i < MTK_DMA_SIZE; i++) {
+		for (i = 0; i < soc->txrx.tx_dma_size; i++) {
 			pdma_txd = ring->dma_pdma + i * sz;
 
 			pdma_txd->txd2 = TX_DMA_DESP2_DEF;
@@ -2860,11 +2867,11 @@
 		}
 	}
 
-	ring->dma_size = MTK_DMA_SIZE;
-	atomic_set(&ring->free_count, MTK_DMA_SIZE - 2);
+	ring->dma_size = soc->txrx.tx_dma_size;
+	atomic_set(&ring->free_count, soc->txrx.tx_dma_size - 2);
 	ring->next_free = ring->dma;
 	ring->last_free = (void *)txd;
-	ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz));
+	ring->last_free_ptr = (u32)(ring->phys + ((soc->txrx.tx_dma_size - 1) * sz));
 	ring->thresh = MAX_SKB_FRAGS;
 	ring->cpu_idx = 0;
 
@@ -2877,14 +2884,14 @@
 		mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr);
 		mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr);
 		mtk_w32(eth,
-			ring->phys + ((MTK_DMA_SIZE - 1) * sz),
+			ring->phys + ((soc->txrx.tx_dma_size - 1) * sz),
 			soc->reg_map->qdma.crx_ptr);
 		mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr);
 		mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES,
 			soc->reg_map->qdma.qtx_cfg);
 	} else {
 		mtk_w32(eth, ring->phys_pdma, soc->reg_map->pdma.tx_ptr);
-		mtk_w32(eth, MTK_DMA_SIZE, soc->reg_map->pdma.tx_cnt_cfg);
+		mtk_w32(eth, soc->txrx.tx_dma_size, soc->reg_map->pdma.tx_cnt_cfg);
 		mtk_w32(eth, ring->cpu_idx, soc->reg_map->pdma.pctx_ptr);
 		mtk_w32(eth, MTK_PST_DTX_IDX_CFG(0), soc->reg_map->pdma.rst_idx);
 	}
@@ -2902,7 +2909,7 @@
 	int i;
 
 	if (ring->buf) {
-		for (i = 0; i < MTK_DMA_SIZE; i++)
+		for (i = 0; i < soc->txrx.tx_dma_size; i++)
 			mtk_tx_unmap(eth, &ring->buf[i], false);
 		kfree(ring->buf);
 		ring->buf = NULL;
@@ -2910,14 +2917,14 @@
 
 	if (!eth->soc->has_sram && ring->dma) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  soc->txrx.tx_dma_size * soc->txrx.txd_size,
 				  ring->dma, ring->phys);
 		ring->dma = NULL;
 	}
 
 	if (ring->dma_pdma) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  soc->txrx.tx_dma_size * soc->txrx.txd_size,
 				  ring->dma_pdma, ring->phys_pdma);
 		ring->dma_pdma = NULL;
 	}
@@ -2926,6 +2933,7 @@
 static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
 {
 	const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+	const struct mtk_soc_data *soc = eth->soc;
 	struct mtk_rx_ring *ring;
 	int rx_data_len, rx_dma_size;
 	int i;
@@ -2944,7 +2952,7 @@
 		rx_dma_size = MTK_HW_LRO_DMA_SIZE;
 	} else {
 		rx_data_len = ETH_DATA_LEN;
-		rx_dma_size = MTK_DMA_SIZE;
+		rx_dma_size = soc->txrx.rx_dma_size;
 	}
 
 	ring->frag_size = mtk_max_frag_size(rx_data_len);
@@ -2970,10 +2978,10 @@
 					       &ring->phys, GFP_KERNEL);
 	else {
 		struct mtk_tx_ring *tx_ring = &eth->tx_ring;
-		ring->dma = tx_ring->dma + MTK_DMA_SIZE *
+		ring->dma = tx_ring->dma + soc->txrx.tx_dma_size *
 			    eth->soc->txrx.txd_size * (ring_no + 1);
-		ring->phys = tx_ring->phys + MTK_DMA_SIZE *
-			     eth->soc->txrx.txd_size * (ring_no + 1);
+		ring->phys = tx_ring->phys + soc->txrx.tx_dma_size *
+			     (dma_addr_t)eth->soc->txrx.txd_size * (ring_no + 1);
 	}
 
 	if (!ring->dma)
@@ -3702,7 +3710,7 @@
 			netdev_reset_queue(eth->netdev[i]);
 	if ( !eth->soc->has_sram && eth->scratch_ring) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  soc->txrx.fq_dma_size * soc->txrx.txd_size,
 				  eth->scratch_ring, eth->phy_scratch_ring);
 		eth->scratch_ring = NULL;
 		eth->phy_scratch_ring = 0;
@@ -3725,9 +3733,9 @@
 			mtk_rx_clean(eth, &eth->rx_ring[MTK_RSS_RING(i)], 1);
 	}
 
-	if (eth->scratch_head) {
-		kfree(eth->scratch_head);
-		eth->scratch_head = NULL;
+	for (i = 0; i < DIV_ROUND_UP(soc->txrx.fq_dma_size, MTK_FQ_DMA_LENGTH); i++) {
+		kfree(eth->scratch_head[i]);
+		eth->scratch_head[i] = NULL;
 	}
 }
 
@@ -3858,8 +3866,16 @@
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		val = mtk_r32(eth, reg_map->qdma.glo_cfg);
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
-		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+			val &= ~(MTK_RESV_BUF_MASK | MTK_DMA_SIZE_MASK);
+			mtk_w32(eth,
+				val | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
+				MTK_DMA_SIZE_16DWORDS | MTK_TX_WB_DDONE |
+				MTK_NDP_CO_PRO | MTK_MUTLI_CNT |
+				MTK_RESV_BUF | MTK_WCOMP_EN |
+				MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN |
+				MTK_RX_2B_OFFSET, reg_map->qdma.glo_cfg);
+		} else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
 			val &= ~MTK_RESV_BUF_MASK;
 			mtk_w32(eth,
 				val | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
@@ -3868,8 +3884,7 @@
 				MTK_RESV_BUF | MTK_WCOMP_EN |
 				MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN |
 				MTK_RX_2B_OFFSET, reg_map->qdma.glo_cfg);
-		}
-		else
+		} else
 			mtk_w32(eth,
 				val | MTK_TX_DMA_EN |
 				MTK_DMA_SIZE_32DWORDS | MTK_NDP_CO_PRO |
@@ -3978,9 +3993,6 @@
 	if (s.base.speed == 0 || s.base.speed == ((__u32)-1))
 		return NOTIFY_DONE;
 
-	if (queue >= MTK_QDMA_TX_NUM)
-		return NOTIFY_DONE;
-
 	if (mac->speed > 0 && mac->speed < s.base.speed)
 		s.base.speed = 0;
 
@@ -5460,6 +5472,8 @@
 		return -ENOMEM;
 
 	eth->soc = of_device_get_match_data(&pdev->dev);
+	if (!eth->soc)
+		return -EINVAL;
 
 	eth->dev = &pdev->dev;
 	eth->dma_dev = &pdev->dev;
@@ -5833,6 +5847,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -5850,6 +5867,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rxd_size = sizeof(struct mtk_rx_dma),
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -5868,6 +5888,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -5885,6 +5908,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -5903,6 +5929,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -5921,6 +5950,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(4K),
+		.rx_dma_size = MTK_DMA_SIZE(1K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -5939,6 +5971,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(4K),
+		.rx_dma_size = MTK_DMA_SIZE(1K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -5957,6 +5992,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma_v2),
+		.tx_dma_size = MTK_DMA_SIZE(4K),
+		.rx_dma_size = MTK_DMA_SIZE(1K),
+		.fq_dma_size = MTK_DMA_SIZE(4K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -5974,6 +6012,9 @@
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
+		.tx_dma_size = MTK_DMA_SIZE(2K),
+		.rx_dma_size = MTK_DMA_SIZE(2K),
+		.fq_dma_size = MTK_DMA_SIZE(2K),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA,
 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
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 355b745..c299a9b 100644
--- 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
@@ -19,7 +19,9 @@
 #define MTK_QDMA_PAGE_SIZE	2048
 #define	MTK_MAX_RX_LENGTH	1536
 #define MTK_MIN_TX_LENGTH	60
-#define MTK_DMA_SIZE		2048
+#define MTK_DMA_SIZE(x)		(SZ_##x)
+#define MTK_FQ_DMA_HEAD		32
+#define MTK_FQ_DMA_LENGTH	2048
 #define MTK_NAPI_WEIGHT		256
 
 #if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -454,6 +456,7 @@
 #define MTK_RX_BT_32DWORDS	(3 << 11)
 #define MTK_NDP_CO_PRO		BIT(10)
 #define MTK_TX_WB_DDONE		BIT(6)
+#define MTK_DMA_SIZE_MASK	GENMASK(5, 4)
 #define MTK_DMA_SIZE_16DWORDS	(2 << 4)
 #define MTK_DMA_SIZE_32DWORDS	(3 << 4)
 #define MTK_RX_DMA_BUSY		BIT(3)
@@ -1720,6 +1723,9 @@
 	struct {
 		u32	txd_size;
 		u32	rxd_size;
+		u32	tx_dma_size;
+		u32	rx_dma_size;
+		u32	fq_dma_size;
 		u32	rx_dma_l4_valid;
 		u32	dma_max_len;
 		u32	dma_len_offset;
@@ -1902,7 +1908,7 @@
 	void				*scratch_ring;
 	struct mtk_reset_event		reset_event;
 	dma_addr_t			phy_scratch_ring;
-	void				*scratch_head;
+	void				*scratch_head[MTK_FQ_DMA_HEAD];
 	struct clk			*clks[MTK_CLK_MAX];
 
 	struct mii_bus			*mii_bus;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 34fc091..f909142 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -2805,7 +2805,7 @@
 		qos_toggle = 1;
 	} else if (buf[0] == '2') {
 		pr_info("Per-port-per-queue mode is going to be enabled!\n");
-		pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
+		pr_info("PPPQ use qid 0~11 (scheduler 0).\n");
 		qos_toggle = 2;
 		qos_dl_toggle = 1;
 		qos_ul_toggle = 1;
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 9fe85fb..579ef9a 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
@@ -832,8 +832,7 @@
 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 };
+	struct flow_offload_hw_path hw_path;
 
 	if (!skb)
 		goto drop;
@@ -848,6 +847,9 @@
 
 	hnat_set_head_frags(state, skb, -1, hnat_set_iif);
 
+	hw_path.dev = skb->dev;
+	hw_path.virt_dev = skb->dev;
+
 	/*
 	 * 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,
@@ -1221,6 +1223,7 @@
 	int udp = 0;
 	u32 qid = 0;
 	u32 port_id = 0;
+	u32 payload_len = 0;
 	int mape = 0;
 	struct mtk_mac *mac = netdev_priv(dev);
 
@@ -1757,6 +1760,29 @@
 	else
 		qid = 0;
 
+	if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) {
+		if (ntohs(eth->h_proto) == ETH_P_IP) {
+			iph = ip_hdr(skb);
+			if (iph->protocol == IPPROTO_TCP) {
+				skb_set_transport_header(skb, sizeof(struct iphdr));
+				payload_len = be16_to_cpu(iph->tot_len) -
+					      skb_transport_offset(skb) - tcp_hdrlen(skb);
+				/* Dispatch ACK packets to high priority queue */
+				if (payload_len == 0)
+					qid += 6;
+			}
+		} else if (ntohs(eth->h_proto) == ETH_P_IPV6) {
+			ip6h = ipv6_hdr(skb);
+			if (ip6h->nexthdr == NEXTHDR_TCP) {
+				skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+				payload_len = be16_to_cpu(ip6h->payload_len) - tcp_hdrlen(skb);
+				/* Dispatch ACK packets to high priority queue */
+				if (payload_len == 0)
+					qid += 6;
+			}
+		}
+	}
+
 	if (IS_IPV4_GRP(foe)) {
 		entry.ipv4_hnapt.iblk2.dp = gmac;
 		entry.ipv4_hnapt.iblk2.port_mg =
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 f114225..0e4d9ee 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
@@ -187,6 +187,8 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
+			   0x20000000);
 	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
@@ -299,6 +301,8 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
+			   0x20000000);
 	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
@@ -411,6 +415,8 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
+			   0x20000000);
 	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
@@ -763,6 +769,7 @@
 {
 	struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
 	unsigned long t_start = jiffies;
+	unsigned int mpcs_mode;
 
 	/* Reconfiguring USXGMII to ensure the quality of the RX signal
 	 * after the line side link up.
@@ -776,7 +783,11 @@
 		if (mtk_usxgmii_link_status(mpcs))
 			return;
 
-		if (mpcs->mode == MLO_AN_PHY)
+		spin_lock(&mpcs->regmap_lock);
+		mpcs_mode = mpcs->mode;
+		spin_unlock(&mpcs->regmap_lock);
+
+		if (mpcs_mode == MLO_AN_PHY)
 			mtk_usxgmii_pcs_config(&mpcs->pcs, mode,
 						interface, NULL, false);
 	} while (time_before(jiffies, t_start + msecs_to_jiffies(3000)));
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
index 38d4c07..2fdbb58 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
@@ -46,7 +46,7 @@
 #define MII_MMD_ADDR_DATA_REG       0x0e
 #define MMD_OP_MODE_DATA            BIT(14)
 
-#define EN8811H_DRIVER_VERSION      "v1.2.4"
+#define EN8811H_DRIVER_VERSION      "v1.2.5"
 
 #define LED_ON_CTRL(i)              (0x024 + ((i)*2))
 #define LED_ON_EN                   (1 << 15)
@@ -99,6 +99,7 @@
 	unsigned int        dsp_crc32;
 	char                buf[512];
 	int                 pol;
+	int                 surge;
 };
 
 struct air_base_t_led_cfg {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
index a73bcee..723275d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
@@ -334,6 +334,22 @@
 	}
 	return ret;
 }
+
+int air_surge_5ohm_config(struct phy_device *phydev)
+{
+	int ret = 0;
+	struct device *dev = phydev_dev(phydev);
+
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x00b0);
+	if (ret < 0)
+		return ret;
+	dev_info(dev, "surge protection mode - 5R\n");
+	return ret;
+}
+
 #if defined(CONFIG_OF)
 int en8811h_of_init(struct phy_device *phydev)
 {
@@ -346,12 +362,12 @@
 	if (of_find_property(of_node, "airoha,polarity", NULL)) {
 		if (of_property_read_u32(of_node, "airoha,polarity",
 					 &val) != 0) {
-			phydev_err(phydev, "airoha,polarity value is invalid.");
+			dev_err(dev, "airoha,polarity value is invalid.");
 			return -EINVAL;
 		}
 		if (val < AIR_POL_TX_REV_RX_NOR ||
 		    val > AIR_POL_TX_NOR_RX_REV) {
-			phydev_err(phydev,
+			dev_err(dev,
 				   "airoha,polarity value %u out of range.",
 				   val);
 			return -EINVAL;
@@ -360,6 +376,25 @@
 	} else
 		priv->pol = AIR_POL_TX_NOR_RX_NOR;
 
+	if (of_find_property(of_node, "airoha,surge", NULL)) {
+		if (of_property_read_u32(of_node, "airoha,surge",
+					 &val) != 0) {
+			dev_err(dev, "airoha,surge value is invalid.");
+			return -EINVAL;
+		}
+		if (val < 0 || val > 1) {
+			dev_err(dev,
+				   "airoha,surge value %u out of range.",
+				   val);
+			return -EINVAL;
+		}
+		if (val)
+			priv->surge = 1;
+		else
+			priv->surge = 0;
+	} else
+		priv->surge = 0;
+
 	return 0;
 }
 #else
@@ -710,7 +745,7 @@
 	seq_puts(seq, "| Tx to Line side_T        :");
 	pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0088);
 	seq_printf(seq, "%010u |\n", pkt_cnt);
-	ret = air_buckpbus_reg_write(phydev, 0xe0074, 0xf);
+	ret = air_buckpbus_reg_write(phydev, 0xe0074, 0x3);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -1169,8 +1204,12 @@
 	u32 pbus_value = 0;
 
 	seq_puts(seq, "<<AIR EN8811H Temp>>\n");
-	air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1100);
-	air_mii_cl45_write(phydev, 0x1e, 0x800f, 0xe5);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1100);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0xe5);
+	if (ret < 0) {
+		pr_notice("\nmii_cl45_write fail\n");
+		return -EIO;
+	}
 	pbus_value = air_buckpbus_reg_read(phydev, 0x3B38);
 	seq_printf(seq, "| Temperature  : %dC |\n",
 						pbus_value);
@@ -1285,6 +1324,114 @@
 	return single_open(file, airphy_lp_speed, inode->i_private);
 }
 
+static void airphy_debugfs_mii_cl22_help(void)
+{
+	pr_notice("\nUsage:\n"
+			"[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n"
+			"Read:\n"
+			"echo r [phy_register] > /[debugfs]/mii_mgr_op\n"
+			"Write:\n"
+			"echo w [phy_register] [value] > /[debugfs]/mii_mgr_op\n");
+}
+
+
+static ssize_t airphy_debugfs_cl22(struct file *file,
+					const char __user *buffer, size_t count,
+					loff_t *data)
+{
+	struct phy_device *phydev = file->private_data;
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int addr = phydev_addr(phydev);
+	char buf[64];
+	int ret = 0;
+	unsigned int reg, val;
+
+	memset(buf, 0, 64);
+	if (count > sizeof(buf) - 1)
+		return -EINVAL;
+	if (copy_from_user(buf, buffer, count))
+		return -EFAULT;
+
+	if (buf[0] == 'w') {
+		if (sscanf(buf, "w %x %x", &reg, &val) == -1)
+			return -EFAULT;
+
+		pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
+			phydev_addr(phydev), reg, val);
+		ret = air_mii_cl22_write(mbus, addr, reg, val);
+		if (ret < 0) {
+			pr_notice("\nmii_cl22_write fail\n");
+			return -EIO;
+		}
+		val = air_mii_cl22_read(mbus, addr, reg);
+		pr_notice("\nphy=%d, reg=0x%x, val=0x%x confirm..\n",
+			phydev_addr(phydev), reg, val);
+	} else if (buf[0] == 'r') {
+		if (sscanf(buf, "r %x", &reg) == -1)
+			return -EFAULT;
+
+		val = air_mii_cl22_read(mbus, addr, reg);
+		pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
+		phydev_addr(phydev), reg, val);
+	} else
+		airphy_debugfs_mii_cl22_help();
+
+	return count;
+}
+
+static void airphy_debugfs_mii_cl45_help(void)
+{
+	pr_notice("\nUsage:\n"
+			"[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n"
+			"Read:\n"
+			"echo r [device number] [phy_register] > /[debugfs]/mii_mgr_cl45_op\n"
+			"Write:\n"
+			"echo w [device number] [phy_register] [value] > /[debugfs]/mii_mgr_cl45_op\n");
+}
+
+
+static ssize_t airphy_debugfs_cl45(struct file *file,
+					const char __user *buffer, size_t count,
+					loff_t *data)
+{
+	struct phy_device *phydev = file->private_data;
+	char buf[64];
+	int ret = 0;
+	unsigned int reg, val, devnum;
+
+	memset(buf, 0, 64);
+	if (count > sizeof(buf) - 1)
+		return -EINVAL;
+	if (copy_from_user(buf, buffer, count))
+		return -EFAULT;
+
+	if (buf[0] == 'w') {
+		if (sscanf(buf, "w %x %x %x", &devnum, &reg, &val) == -1)
+			return -EFAULT;
+
+		pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x\n",
+			phydev_addr(phydev), devnum, reg, val);
+		ret = air_mii_cl45_write(phydev, devnum, reg, val);
+		if (ret < 0) {
+			pr_notice("\nmii_cl45_write fail\n");
+			return -EIO;
+		}
+		val = air_mii_cl45_read(phydev, devnum, reg);
+		pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x confirm..\n",
+			phydev_addr(phydev), devnum, reg, val);
+	} else if (buf[0] == 'r') {
+		if (sscanf(buf, "r %x %x", &devnum, &reg) == -1)
+			return -EFAULT;
+
+		val = air_mii_cl45_read(phydev, devnum, reg);
+		pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x\n",
+		phydev_addr(phydev), devnum, reg, val);
+	} else
+		airphy_debugfs_mii_cl45_help();
+
+	return count;
+}
+
 static const struct file_operations airphy_lp_speed_fops = {
 	.owner = THIS_MODULE,
 	.open = airphy_lp_speed_open,
@@ -1361,6 +1508,20 @@
 	.release = single_release,
 };
 
+static const struct file_operations airphy_debugfs_cl22_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.write = airphy_debugfs_cl22,
+	.llseek = noop_llseek,
+};
+
+static const struct file_operations airphy_debugfs_cl45_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.write = airphy_debugfs_cl45,
+	.llseek = noop_llseek,
+};
+
 int airphy_debugfs_init(struct phy_device *phydev)
 {
 	int ret = 0;
@@ -1404,6 +1565,12 @@
 	debugfs_create_file(DEBUGFS_LP_SPEED, S_IFREG | 0444,
 					dir, phydev,
 					&airphy_lp_speed_fops);
+	debugfs_create_file(DEBUGFS_MII_CL22_OP, S_IFREG | 0200,
+					dir, phydev,
+					&airphy_debugfs_cl22_fops);
+	debugfs_create_file(DEBUGFS_MII_CL45_OP, S_IFREG | 0200,
+					dir, phydev,
+					&airphy_debugfs_cl45_fops);
 
 	priv->debugfs_root = dir;
 	return ret;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
index 9715a58..dd4f7b1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
@@ -31,6 +31,8 @@
 #define DEBUGFS_DBG_REG_SHOW        "dbg_regs_show"
 #define DEBUGFS_TEMPERATURE         "temp"
 #define DEBUGFS_LP_SPEED            "lp_speed"
+#define DEBUGFS_MII_CL22_OP          "cl22_op"
+#define DEBUGFS_MII_CL45_OP		     "cl45_op"
 
 enum air_port_mode {
 	AIR_PORT_MODE_FORCE_100,
@@ -82,6 +84,7 @@
 int air_buckpbus_reg_write(struct phy_device *phydev,
 	unsigned int pbus_address, unsigned int pbus_data);
 int en8811h_of_init(struct phy_device *phydev);
+int air_surge_5ohm_config(struct phy_device *phydev);
 #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 int airphy_debugfs_init(struct phy_device *phydev);
 void airphy_debugfs_remove(struct phy_device *phydev);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
index 50a7f49..d01169b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
@@ -35,6 +35,7 @@
  * GPIO3  <-> BASE_T_LED2,
  **************************/
 /* User-defined.B */
+/*#define AIR_MD32_FW_CHECK*/
 #define AIR_LED_SUPPORT
 #ifdef AIR_LED_SUPPORT
 static const struct air_base_t_led_cfg led_cfg[3] = {
@@ -52,9 +53,45 @@
 /***********************************************************
  *                  F U N C T I O N S
  ***********************************************************/
+static void air_mdio_read_buf(struct phy_device *phydev, unsigned long address,
+			const struct firmware *fw, unsigned int *crc32)
+{
+	unsigned int write_data, offset;
+	int ret = 0, len = 0;
+	unsigned int pbus_data_low, pbus_data_high;
+	struct device *dev = phydev_dev(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int addr = phydev_addr(phydev);
+	char *buf = kmalloc(fw->size, GFP_KERNEL);
 
+	memset(buf, '\0', fw->size);
+	/* page 4 */
+	ret |= air_mii_cl22_write(mbus, addr, 0x1F, 4);
+	/* address increment*/
+	ret |= air_mii_cl22_write(mbus, addr, 0x10, 0x8000);
+	ret |= air_mii_cl22_write(mbus, addr,
+			0x15, (unsigned int)((address >> 16) & 0xffff));
+	ret |= air_mii_cl22_write(mbus, addr,
+			0x16, (unsigned int)(address & 0xffff));
+	for (offset = 0; offset < fw->size; offset += 4) {
+		pbus_data_high = air_mii_cl22_read(mbus, addr, 0x17);
+		pbus_data_low = air_mii_cl22_read(mbus, addr, 0x18);
+		buf[offset + 0] = pbus_data_low & 0xff;
+		buf[offset + 1] = (pbus_data_low & 0xff00) >> 8;
+		buf[offset + 2] = pbus_data_high & 0xff;
+		buf[offset + 3] = (pbus_data_high & 0xff00) >> 8;
+	}
+	msleep(100);
+	*crc32 = ~crc32(~0, buf, fw->size);
+	ret |= air_mii_cl22_write(mbus, addr, 0x1F, 0);
+	kfree(buf);
+	if (ret) {
+		dev_info(dev, "%s 0x%lx FAIL(ret:%d)\n",
+				__func__, address, ret);
+	}
+}
 
-static int MDIOWriteBuf(struct phy_device *phydev,
+static int air_mdio_write_buf(struct phy_device *phydev,
 		unsigned long address, const struct firmware *fw)
 {
 	unsigned int write_data, offset;
@@ -115,6 +152,10 @@
 	const char *firmware;
 	int ret = 0;
 	u32 pbus_value = 0;
+#ifdef AIR_MD32_FW_CHECK
+	unsigned int d_crc32 = 0, crc32 = 0;
+	int retry = 0;
+#endif
 	struct en8811h_priv *priv = phydev->priv;
 
 	ret = air_buckpbus_reg_write(phydev,
@@ -138,12 +179,12 @@
 	dev_info(dev, "%s: crc32=0x%x\n",
 		firmware, ~crc32(~0, fw->data, fw->size));
 	/* Download DM */
-	ret = MDIOWriteBuf(phydev, 0x00000000, fw);
+	ret = air_mdio_write_buf(phydev, 0x00000000, fw);
 	release_firmware(fw);
 	if (ret < 0) {
 		dev_err(dev,
-			"MDIOWriteBuf 0x00000000 fail, ret: %d\n", ret);
-		return ret;
+			"air_mdio_write_buf 0x00000000 fail, ret: %d\n", ret);
+		goto release;
 	}
 
 	firmware = EN8811H_MD32_DSP;
@@ -157,22 +198,56 @@
 	dev_info(dev, "%s: crc32=0x%x\n",
 		firmware, ~crc32(~0, fw->data, fw->size));
 	/* Download PM */
-	ret = MDIOWriteBuf(phydev, 0x00100000, fw);
-	release_firmware(fw);
+	ret = air_mdio_write_buf(phydev, 0x00100000, fw);
 	if (ret < 0) {
 		dev_err(dev,
-			"MDIOWriteBuf 0x00100000 fail , ret: %d\n", ret);
-		return ret;
+			"air_mdio_write_buf 0x00100000 fail , ret: %d\n", ret);
+		goto release;
 	}
 	pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
 	pbus_value &= ~BIT(11);
 	ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
 	if (ret < 0)
-		return ret;
+		goto release;
+#ifdef AIR_MD32_FW_CHECK
+	crc32 = ~crc32(~0, fw->data, fw->size);
+	/* Check PM */
+	air_mdio_read_buf(phydev, 0x100000, fw, &d_crc32);
+	if (d_crc32 == crc32)
+		dev_info(dev, "0x00100000 Check Sum Pass.\n");
+	else {
+		dev_info(dev, "0x00100000 Check Sum Fail.\n");
+		dev_info(dev, "CRC32 0x%x != Caculated CRC32 0x%x\n",
+					crc32, d_crc32);
+	}
+	release_firmware(fw);
+	retry = MAX_RETRY;
+	do {
+		ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
+		if (ret < 0)
+			return ret;
+		msleep(100);
+		pbus_value = air_buckpbus_reg_read(phydev, 0x0f0018);
+		if (retry == 0) {
+			dev_err(dev,
+				"Release Software Reset fail , ret: %d\n",
+						pbus_value);
+			break;
+		}
+		retry--;
+	} while (pbus_value != 0x1);
+	dev_info(dev,
+		"Release Software Reset successful.\n");
+#else
+	release_firmware(fw);
 	ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
 	if (ret < 0)
 		return ret;
+#endif
 	return 0;
+release:
+	release_firmware(fw);
+	return ret;
 }
 
 #ifdef AIR_LED_SUPPORT
@@ -383,20 +458,12 @@
 			"EN8811H initialize fail!\n");
 		goto priv_free;
 	}
-	/* Mode selection*/
-	dev_info(dev, "EN8811H Mode 1 !\n");
-	ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
-	if (ret < 0)
-		goto priv_free;
-	ret = air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
+	ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
 	if (ret < 0)
 		goto priv_free;
-	ret = air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
-	if (ret < 0)
-		goto priv_free;
-	ret = air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
-	if (ret < 0)
-		goto priv_free;
 	/* Serdes polarity */
 	ret = en8811h_of_init(phydev);
 	if (ret < 0)
@@ -415,6 +482,13 @@
 	dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
 	pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
 	dev_info(dev, "MD32 FW Version : %08x\n", pbus_value);
+	if (priv->surge) {
+		ret = air_surge_5ohm_config(phydev);
+		if (ret < 0)
+			dev_err(dev,
+				"air_surge_5ohm_config fail. (ret=%d)\n", ret);
+	} else
+		dev_info(dev, "Surge Protection Mode - 0R\n");
 #if defined(AIR_LED_SUPPORT)
 	ret = en8811h_led_init(phydev);
 	if (ret < 0) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
deleted file mode 100644
index 86d3edb..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
+++ /dev/null
@@ -1,222 +0,0 @@
-From 4136e3567f6904259babbe5ae5c0d0bf06413f57 Mon Sep 17 00:00:00 2001
-From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Wed, 25 Oct 2023 09:21:06 +0800
-Subject: [PATCH] 999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K
-
----
- drivers/net/ethernet/mediatek/mtk_eth_dbg.c   |  2 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 74 ++++++++++---------
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  5 +-
- .../ethernet/mediatek/mtk_hnat/hnat_debugfs.c |  2 +-
- .../ethernet/mediatek/mtk_hnat/hnat_nf_hook.c | 23 ++++++
- 5 files changed, 69 insertions(+), 37 deletions(-)
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
-index e50e1ac..7c137e5 100755
---- a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
-@@ -882,7 +882,7 @@ int hwtx_ring_read(struct seq_file *seq, void *v)
- 	struct mtk_tx_dma_v2 *hwtx_ring;
- 	int i = 0;
- 
--	for (i = 0; i < MTK_DMA_SIZE; i++) {
-+	for (i = 0; i < MTK_DMA_FQ_SIZE; i++) {
- 		dma_addr_t addr = eth->phy_scratch_ring +
- 				  i * (dma_addr_t)eth->soc->txrx.txd_size;
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 1226dd6..fe9c1de 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -1557,10 +1557,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
- {
- 	const struct mtk_soc_data *soc = eth->soc;
- 	dma_addr_t phy_ring_tail;
--	int cnt = MTK_DMA_SIZE;
-+	int cnt = MTK_DMA_FQ_SIZE;
- 	dma_addr_t dma_addr;
- 	u64 addr64 = 0;
--	int i;
-+	int i, j, len;
- 
- 	if (!eth->soc->has_sram) {
- 		eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
-@@ -1577,40 +1577,44 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
- 	if (unlikely(!eth->scratch_ring))
-                         return -ENOMEM;
- 
--	eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
--	if (unlikely(!eth->scratch_head))
--		return -ENOMEM;
--
--	dma_addr = dma_map_single(eth->dma_dev,
--				  eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE,
--				  DMA_FROM_DEVICE);
--	if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
--		return -ENOMEM;
--
- 	phy_ring_tail = eth->phy_scratch_ring +
- 			(dma_addr_t)soc->txrx.txd_size * (cnt - 1);
- 
--	for (i = 0; i < cnt; i++) {
--		struct mtk_tx_dma_v2 *txd;
-+	for (j = 0; j < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); j++) {
-+		len = min_t(int, cnt - j * MTK_DMA_FQ_LENGTH, MTK_DMA_FQ_LENGTH);
- 
--		txd = eth->scratch_ring + i * soc->txrx.txd_size;
--		txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
--		if (i < cnt - 1)
--			txd->txd2 = eth->phy_scratch_ring +
--				(i + 1) * soc->txrx.txd_size;
-+		eth->scratch_head[j] = kcalloc(len, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
-+		if (unlikely(!eth->scratch_head[j]))
-+			return -ENOMEM;
- 
--		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
--			  TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
-+		dma_addr = dma_map_single(eth->dma_dev,
-+					  eth->scratch_head[j], len * MTK_QDMA_PAGE_SIZE,
-+					  DMA_FROM_DEVICE);
-+		if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
-+			return -ENOMEM;
- 
--		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
--		txd->txd4 = 0;
-+		for (i = 0; i < len; i++) {
-+			struct mtk_tx_dma_v2 *txd;
- 
--		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
--		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
--			txd->txd5 = 0;
--			txd->txd6 = 0;
--			txd->txd7 = 0;
--			txd->txd8 = 0;
-+			txd = eth->scratch_ring + (j * MTK_DMA_FQ_LENGTH + i) * soc->txrx.txd_size;
-+			txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
-+			if (j * MTK_DMA_FQ_LENGTH + i < cnt)
-+				txd->txd2 = eth->phy_scratch_ring +
-+					(j * MTK_DMA_FQ_LENGTH + i + 1) * soc->txrx.txd_size;
-+
-+			addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
-+				  TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
-+
-+			txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
-+			txd->txd4 = 0;
-+
-+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
-+			    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
-+				txd->txd5 = 0;
-+				txd->txd6 = 0;
-+				txd->txd7 = 0;
-+				txd->txd8 = 0;
-+			}
- 		}
- 	}
- 
-@@ -2541,9 +2545,9 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
- 		ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
- 					       &ring->phys, GFP_KERNEL);
- 	else {
--		ring->dma =  eth->sram_base + MTK_DMA_SIZE * sz;
-+		ring->dma =  eth->sram_base + MTK_DMA_FQ_SIZE * sz;
- 		ring->phys = eth->phy_scratch_ring +
--			     MTK_DMA_SIZE * (dma_addr_t)sz;
-+			     MTK_DMA_FQ_SIZE * (dma_addr_t)sz;
- 	}
- 
- 	if (!ring->dma)
-@@ -3349,9 +3353,11 @@ static void mtk_dma_free(struct mtk_eth *eth)
- 			mtk_rx_clean(eth, &eth->rx_ring[MTK_RSS_RING(i)], 1);
- 	}
- 
--	if (eth->scratch_head) {
--		kfree(eth->scratch_head);
--		eth->scratch_head = NULL;
-+	for (i = 0; i < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); i++) {
-+		if (eth->scratch_head[i]) {
-+			kfree(eth->scratch_head[i]);
-+			eth->scratch_head[i] = NULL;
-+		}
- 	}
- }
- 
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index fe8bdee..cd2de23 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -20,6 +20,9 @@
- #define	MTK_MAX_RX_LENGTH	1536
- #define MTK_MIN_TX_LENGTH	60
- #define MTK_DMA_SIZE		2048
-+#define MTK_DMA_FQ_SIZE		4096
-+#define MTK_DMA_FQ_HEAD		32
-+#define MTK_DMA_FQ_LENGTH	2048
- #define MTK_NAPI_WEIGHT		256
- 
- #if defined(CONFIG_MEDIATEK_NETSYS_V3)
-@@ -1837,7 +1840,7 @@ struct mtk_eth {
- 	void				*scratch_ring;
- 	struct mtk_reset_event		reset_event;
- 	dma_addr_t			phy_scratch_ring;
--	void				*scratch_head;
-+	void				*scratch_head[MTK_DMA_FQ_HEAD];
- 	struct clk			*clks[MTK_CLK_MAX];
- 
- 	struct mii_bus			*mii_bus;
-diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
-index fc7d216..b97fd6a 100644
---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
-@@ -2784,7 +2784,7 @@ static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffe
- 		qos_toggle = 1;
- 	} else if (buf[0] == '2') {
- 		pr_info("Per-port-per-queue mode is going to be enabled!\n");
--		pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
-+		pr_info("PPPQ use qid 0~11 (scheduler 0).\n");
- 		qos_toggle = 2;
- 		qos_dl_toggle = 1;
- 		qos_ul_toggle = 1;
-diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-index 85c38e0..6a373f8 100644
---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-@@ -1219,6 +1219,7 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- 	int udp = 0;
- 	u32 qid = 0;
- 	u32 port_id = 0;
-+	u32 payload_len = 0;
- 	int mape = 0;
- 
- 	ct = nf_ct_get(skb, &ctinfo);
-@@ -1748,6 +1749,28 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- 	else
- 		qid = 0;
- 
-+	if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) {
-+		if (ntohs(eth->h_proto) == ETH_P_IP) {
-+			iph = ip_hdr(skb);
-+			if (iph->protocol == IPPROTO_TCP) {
-+				skb_set_transport_header(skb, sizeof(struct iphdr));
-+				payload_len = be16_to_cpu(iph->tot_len) - skb_transport_offset(skb) - tcp_hdrlen(skb);
-+				/* Dispatch ACK packets to high priority queue */
-+				if (payload_len == 0)
-+					qid += 6;
-+			}
-+		} else if (ntohs(eth->h_proto) == ETH_P_IPV6) {
-+			ip6h = ipv6_hdr(skb);
-+			if (ip6h->nexthdr == NEXTHDR_TCP) {
-+				skb_set_transport_header(skb, sizeof(struct ipv6hdr));
-+				payload_len = be16_to_cpu(ip6h->payload_len) - tcp_hdrlen(skb);
-+				/* Dispatch ACK packets to high priority queue */
-+				if (payload_len == 0)
-+					qid += 6;
-+			}
-+		}
-+	}
-+
- 	if (IS_IPV4_GRP(foe)) {
- 		entry.ipv4_hnapt.iblk2.dp = gmac;
- 		entry.ipv4_hnapt.iblk2.port_mg =
--- 
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
index dc060ea..afd633a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
@@ -1,4 +1,4 @@
-From 4d7eabd37042f541f085cca6265bd22ae3f05e6e Mon Sep 17 00:00:00 2001
+From 2d5090dc6072979167593c8fee026341774efb53 Mon Sep 17 00:00:00 2001
 From: mtk22468 <Xuzhu.Wang@mediatek.com>
 Date: Mon, 18 Sep 2023 10:50:36 +0800
 Subject: [PATCH] ovs add multicast to unicast support
@@ -6,13 +6,13 @@
 ---
  net/openvswitch/actions.c  |  30 ++++
  net/openvswitch/datapath.c | 290 +++++++++++++++++++++++++++++++++++++
- net/openvswitch/datapath.h |  32 ++++
+ net/openvswitch/datapath.h |  40 +++++
  net/openvswitch/vport.c    |   8 +
  net/openvswitch/vport.h    |  26 ++++
- 5 files changed, 386 insertions(+)
+ 5 files changed, 394 insertions(+)
 
 diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
-index 9e8a5c4..e953e62 100644
+index 9e8a5c4..82cd46e 100644
 --- a/net/openvswitch/actions.c
 +++ b/net/openvswitch/actions.c
 @@ -919,6 +919,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -30,7 +30,7 @@
  
  		if (likely(!mru ||
  		           (skb->len <= mru + vport->dev->hard_header_len))) {
-+			if (is_multicast_addr(skb) && !is_igmp_mld(skb)) {
++			if (is_multicast_addr(skb) && !is_igmp_mld(skb) && !is_icmpv6_ndp_rs_ra(skb)) {
 +				mdb = vport->mdb;
 +				spin_lock_bh(&mdb->tbl_lock);
 +				list_for_each_entry(table, &mdb->list_head, mdb_node) {
@@ -60,7 +60,7 @@
  		} else if (mru <= vport->dev->mtu) {
  			struct net *net = read_pnet(&dp->net);
 diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
-index 4c537e7..e6787cc 100644
+index 4c537e7..0c8d344 100644
 --- a/net/openvswitch/datapath.c
 +++ b/net/openvswitch/datapath.c
 @@ -11,6 +11,9 @@
@@ -349,7 +349,7 @@
  	OVS_CB(packet)->input_vport = input_vport;
  	sf_acts = rcu_dereference(flow->sf_acts);
  
-+	if (is_multicast_addr(packet))
++	if (is_multicast_addr(packet) && !is_icmpv6_ndp_rs_ra(packet))
 +		ovs_multicast_rcv(packet, input_vport);
 +
  	local_bh_disable();
@@ -389,10 +389,10 @@
  	ovs_dp_detach_port(vport);
  
 diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
-index 81e85dd..6830d3b 100644
+index 81e85dd..50596bc 100644
 --- a/net/openvswitch/datapath.h
 +++ b/net/openvswitch/datapath.h
-@@ -215,6 +215,38 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
+@@ -215,6 +215,46 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
  	return dp;
  }
  
@@ -428,6 +428,14 @@
 +	return err;
 +}
 +
++static inline bool is_icmpv6_ndp_rs_ra(struct sk_buff *skb)
++{
++	if (!skb)
++		return 0;
++
++	return ((icmp6_hdr(skb)->icmp6_type == NDISC_ROUTER_SOLICITATION) && (icmp6_hdr(skb)->icmp6_type == NDISC_ROUTER_ADVERTISEMENT));
++}
++
  extern struct notifier_block ovs_dp_device_notifier;
  extern struct genl_family dp_vport_genl_family;
  
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch
index 9307157..3a5aa25 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch
@@ -1,4 +1,4 @@
-From da90def8adfa6139e8710c282a41024cfc4b23b3 Mon Sep 17 00:00:00 2001
+From b6e8f376899070b8109c3413b15e572f8f03dc06 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Mon, 18 Sep 2023 13:21:15 +0800
 Subject: [PATCH] mtk:wed:add wed3 support
@@ -392,7 +392,7 @@
  		return err;
  
 diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index a7d2166..92df014 100644
+index a7d2166..ab561f7 100644
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
 @@ -23,9 +23,45 @@
@@ -614,7 +614,7 @@
 +	}
 +
 +	/* eagle E1 PCIE1 tx ring 22 flow control issue */
-+	if (dev->wlan.id == 0x7991)
++	if (dev->wlan.id == 0x7991 || dev->wlan.id == 0x7992)
 +		wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING);
 +
 +	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
index e62c331..0ca0e3a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
@@ -1,37 +1,46 @@
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -1856,6 +1856,12 @@ static void mtk_tx_set_dma_desc_v3(struc
- 
+@@ -1992,6 +1992,17 @@ static void mtk_tx_set_dma_desc_v3(struc
  	trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
  		     __func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
+ #endif
 +
 +	/* forward to eip197 if this packet is going to encrypt */
-+	if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
++	if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_hnat_cdrt(skb) && is_magic_tag_valid(skb)))
++#else
++	if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_tnl_cdrt(skb) && is_tnl_tag_valid(skb)))
++#endif // hnat
++	{
 +		data &= ((~TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT);
 +		data |= (EIP197_QDMA_TPORT & TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT;
 +	}
- #endif
  	WRITE_ONCE(desc->txd4, data);
  
-@@ -1879,6 +1885,17 @@ static void mtk_tx_set_dma_desc_v3(struc
+ 	data = 0;
+@@ -2014,6 +2025,21 @@ static void mtk_tx_set_dma_desc_v3(struc
  
  	WRITE_ONCE(desc->txd7, 0);
  	WRITE_ONCE(desc->txd8, 0);
 +
 +#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
-+	if (unlikely(skb->inner_protocol == IPPROTO_ESP &&skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
++	if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
 +		/* carry cdrt index for encryption */
 +		data = (skb_hnat_cdrt(skb) & TX_DMA_CDRT_MASK) << TX_DMA_CDRT_SHIFT;
 +		WRITE_ONCE(desc->txd8, data);
 +		skb_hnat_magic_tag(skb) = 0;
-+	} else {
-+		WRITE_ONCE(desc->txd8, 0);
 +	}
-+#endif
++#else
++	if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_tnl_cdrt(skb) && is_tnl_tag_valid(skb))) {
++		data = (skb_tnl_cdrt(skb) & TX_DMA_CDRT_MASK) << TX_DMA_CDRT_SHIFT;
++		WRITE_ONCE(desc->txd8, data);
++		skb_tnl_magic_tag(skb) = 0;
++	}
++#endif // hnat
  }
  
- static void mtk_tx_set_dma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
-@@ -2308,6 +2325,7 @@ static int mtk_poll_rx(struct napi_struc
+ static void mtk_tx_set_pdma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
+@@ -2491,6 +2517,7 @@ static int mtk_poll_rx(struct napi_struc
  
  		skb_hnat_alg(skb) = 0;
  		skb_hnat_filled(skb) = 0;
@@ -141,7 +150,7 @@
  static unsigned int skb_to_hnat_info(struct sk_buff *skb,
  				     const struct net_device *dev,
  				     struct foe_entry *foe,
-@@ -2360,6 +2439,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+@@ -2363,6 +2442,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
  
  	skb_hnat_alg(skb) = 0;
  	skb_hnat_set_tops(skb, 0);
@@ -149,7 +158,7 @@
  	skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
  
  	if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -2446,7 +2526,8 @@ static unsigned int mtk_hnat_accel_type(
+@@ -2449,7 +2529,8 @@ static unsigned int mtk_hnat_accel_type(
  	 * is from local_out which is also filtered in sanity check.
  	 */
  	dst = skb_dst(skb);
@@ -159,7 +168,7 @@
  		return 0;
  
  	ct = nf_ct_get(skb, &ctinfo);
-@@ -2850,6 +2931,14 @@ static unsigned int mtk_hnat_nf_post_rou
+@@ -2853,6 +2934,14 @@ static unsigned int mtk_hnat_nf_post_rou
  		}
  	}
  
@@ -174,7 +183,7 @@
  	if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
  		is_virt_dev = true;
  
-@@ -3159,7 +3248,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+@@ -3162,7 +3251,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
  	if (iph->protocol == IPPROTO_IPV6) {
  		entry->udib1.pkt_type = IPV6_6RD;
  		hnat_set_head_frags(state, skb, 0, hnat_set_alg);
@@ -217,7 +226,7 @@
  #define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
 --- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
 +++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
-@@ -49,6 +49,8 @@ int (*mtk_tnl_decap_offload)(struct sk_b
+@@ -54,6 +54,8 @@ int (*mtk_tnl_decap_offload)(struct sk_b
  EXPORT_SYMBOL(mtk_tnl_decap_offload);
  bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb) = NULL;
  EXPORT_SYMBOL(mtk_tnl_decap_offloadable);
@@ -228,7 +237,7 @@
  {
 --- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
 +++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1140,6 +1140,8 @@ enum FoeIpAct {
+@@ -1146,6 +1146,8 @@ enum FoeIpAct {
  #define NR_WDMA1_PORT 9
  #define NR_WDMA2_PORT 13
  #define NR_GMAC3_PORT 15
@@ -237,7 +246,7 @@
  #define NR_TDMA_TPORT 4
  #define NR_TDMA_QDMA_TPORT 5
  #define LAN_DEV_NAME hnat_priv->lan
-@@ -1292,6 +1294,8 @@ extern int qos_toggle;
+@@ -1298,6 +1300,8 @@ extern int qos_toggle;
  extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb);
  extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
  extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
@@ -248,9 +257,9 @@
  int ext_if_del(struct extdev_entry *ext_entry);
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -558,6 +558,10 @@
- 
+@@ -592,6 +592,10 @@
  #define MTK_QDMA_GMAC2_QID	8
+ #define MTK_QDMA_GMAC3_QID	6
  
 +/* QDMA V2 descriptor txd8 */
 +#define TX_DMA_CDRT_SHIFT 	0
@@ -259,7 +268,7 @@
  /* QDMA V2 descriptor txd6 */
  #define TX_DMA_INS_VLAN_V2         BIT(16)
  
-@@ -567,6 +571,9 @@
+@@ -601,6 +605,9 @@
  #define TX_DMA_SPTAG_V3            BIT(27)
  
  /* QDMA V2 descriptor txd4 */
@@ -269,3 +278,47 @@
  #define TX_DMA_FPORT_SHIFT_V2      8
  #define TX_DMA_FPORT_MASK_V2       0xf
  #define TX_DMA_SWC_V2              BIT(30)
+@@ -1063,6 +1070,43 @@
+ #define MT7628_SDM_MAC_ADRL	(MT7628_SDM_OFFSET + 0x0c)
+ #define MT7628_SDM_MAC_ADRH	(MT7628_SDM_OFFSET + 0x10)
+ 
++#if !defined(CONFIG_NET_MEDIATEK_HNAT) && !defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++struct tnl_desc {
++	u32 entry : 15;
++	u32 filled : 3;
++	u32 crsn : 5;
++	u32 resv1 : 3;
++	u32 sport : 4;
++	u32 resv2 : 1;
++	u32 alg : 1;
++	u32 iface : 8;
++	u32 wdmaid : 2;
++	u32 rxid : 2;
++	u32 wcid : 16;
++	u32 bssid : 8;
++	u32 usr_info : 16;
++	u32 tid : 4;
++	u32 is_fixedrate : 1;
++	u32 is_prior : 1;
++	u32 is_sp : 1;
++	u32 hf : 1;
++	u32 amsdu : 1;
++	u32 tops : 6;
++	u32 is_decap : 1;
++	u32 cdrt : 8;
++	u32 resv3 : 4;
++	u32 magic_tag_protect : 16;
++} __packed;
++
++#define TNL_MAGIC_TAG 0x6789
++#define skb_tnl_cdrt(skb) (((struct tnl_desc *)((skb)->head))->cdrt)
++#define skb_tnl_set_cdrt(skb, cdrt) ((skb_tnl_cdrt(skb)) = (cdrt))
++#define skb_tnl_magic_tag(skb) (((struct tnl_desc *)((skb)->head))->magic_tag_protect)
++#define is_tnl_tag_valid(skb) (skb_tnl_magic_tag(skb) == TNL_MAGIC_TAG)
++#endif // NetsysV3
++#endif // hnat
++
+ struct mtk_rx_dma {
+ 	unsigned int rxd1;
+ 	unsigned int rxd2;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch
index d40cbfb..fb959ce 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch
@@ -81,7 +81,7 @@
  	};
  
  	cpus {
-@@ -40,23 +39,36 @@
+@@ -39,23 +39,36 @@
  
  	gpio-keys {
  		compatible = "gpio-keys";
@@ -99,9 +99,9 @@
  			linux,code = <KEY_WPS_BUTTON>;
 -			gpios = <&pio 102 0>;
 +			gpios = <&pio 102 GPIO_ACTIVE_LOW>;
-+		};
-+	};
-+
+ 		};
+ 	};
+ 
 +	leds {
 +		compatible = "gpio-leds";
 +
@@ -113,10 +113,10 @@
 +		red {
 +			label = "bpi-r64:pio:red";
 +			gpios = <&pio 88 GPIO_ACTIVE_HIGH>;
- 		};
- 	};
- 
- 	memory {
++ 		};
++ 	};
++	
+ 	memory@40000000 {
 -		reg = <0 0x40000000 0 0x20000000>;
 +		reg = <0 0x40000000 0 0x40000000>;
  	};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch
index df4f9f9..d3434eb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch
@@ -477,7 +477,7 @@
 +		     SPINAND_HAS_QE_BIT,
  		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
 -	SPINAND_INFO("MX35LF4GE4AD", 0x37,
--		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+-		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
 +	SPINAND_INFO("MX35LF2G24AD",
 +		     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/mediatek/patches-5.4/999-2601-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
index 80ce145..1707d20 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2601-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
@@ -54,23 +54,3 @@
  	.chip	= &mtk_msi_irq_chip,
  };
  
-@@ -627,14 +627,14 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
- 		if (status & MSI_STATUS){
- 			unsigned long imsi_status;
- 
-+			/* Clear MSI interrupt status */
-+			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
- 			while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
- 				for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) {
- 					virq = irq_find_mapping(port->inner_domain, bit);
- 					generic_handle_irq(virq);
- 				}
- 			}
--			/* Clear MSI interrupt status */
--			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
- 		}
- 	}
- 
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index a6e6a07..746a7dc 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -9,8 +9,8 @@
 
 KBRANCH ?= "linux-5.4.y"
 
-LINUX_VERSION ?= "5.4.260"
-SRCREV_machine ?= "87e8e7a7aa1f96276252a90373de1d56add31918"
+LINUX_VERSION ?= "5.4.271"
+SRCREV_machine ?= "3fec063b052e395f4920fbc59a8d0bb3c9666d76"
 KMETA = "kernel-meta"
 SRCREV_meta ?= "feeb59687bc0f054af837a5061f8d413ec7c93e9"