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

[Description]
1db0b0a4 [kernel][mt7988][hnat][Update PPPQ and HQOS coexistense feature]
782aac63 [openwrt][mt7988][crypto][Refactor patch for buiild error]
f60b4934 [kernel][mt7988][hnat][Fix issue with HNAT BIND during LAN WAN role swap]
4cead020 [openwrt][common][sdk][Refactor support for clangd]
3542715a [[openwrt][mt7988][config][feature support] nat forward packet need carry customer's dscp ]
a07cd80b [kernel][mt7988][pcie][Add PCIe IRQ affinity support]
f8c8d651 [kernel][common][app][Add multiple QDMA TX queue scheduler support]
bd9b026c [kernel][common][hnat][Fix QDMA TX queue page error issue]
5182b757 [kernel][mt7988][hnat][Update hnat_entry command for the PPE2]
878fcade [openwrt][common][sdk][Add support to generate compile_commands.json for clangd]
8cb31acd [[7992][CASAN] CASAN image for FW CASAN test]
4ffec28d [MAC80211][hnat][Fix ETH bring up issue for the mt7622]
465d1cf9 [openwrt][mt7988][crypto][Refactor xfrm packet mode path]
5b4771fb [openwrt][mt7988][crypto][Refactor binding path for IPsec encryption]
287a3c9a [openwrt][mt7988][crypto][Change ipsec hw offload path in xfrm framework]
a9740c14 [kernel][mt7988][i2.5gphy][net: phy: Hook suspend/resume function]
c371fba0 [openwrt][mt7988][image][Add hkdf to mt7988.mk]

[Release-log]

Change-Id: I78e1040f501c2060734f9d4b75e387673d61efce
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
new file mode 100644
index 0000000..3d21585
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
@@ -0,0 +1,568 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-spim-snand-CASAN",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	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 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x7080000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	sound_wm8960 {
+		compatible = "mediatek,mt79xx-wm8960-machine";
+		mediatek,platform = <&afe>;
+		audio-routing = "Headphone", "HP_L",
+				"Headphone", "HP_R",
+				"LINPUT1", "AMIC",
+				"RINPUT1", "AMIC";
+		mediatek,audio-codec = <&wm8960>;
+		status = "disabled";
+	};
+
+	sound_si3218x {
+		compatible = "mediatek,mt79xx-si3218x-machine";
+		mediatek,platform = <&afe>;
+		mediatek,ext-codec = <&proslic_spi>;
+		status = "disabled";
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&afe {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcm_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	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;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+
+	wm8960: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+	};
+
+	zts8032: zts8032@77 {
+		compatible = "zilltek,zts8032";
+		reg = <0x76>;
+	};
+
+	dps368: dps368@77 {
+		compatible = "infineon,dps310";
+		reg = <0x77>;
+	};
+
+	rtq6056: rtq6056@40 {
+		compatible = "richtek,rtq6056";
+		reg = <0x40>;
+		shunt-resistor-micro-ohms = <10000>;
+		#io-channel-cells = <1>;
+	};
+};
+
+&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";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+
+	proslic_spi: proslic_spi@0 {
+		compatible = "silabs,proslic_spi";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+		spi-cpha = <1>;
+		spi-cpol = <1>;
+		channel_count = <1>;
+		debug_level = <4>;       /* 1 = TRC, 2 = DBG, 4 = ERR */
+		reset_gpio = <&pio 54 0>;
+		ig,enable-spi = <1>;     /* 1: Enable, 0: Disable */
+	};
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	mdio0_pins: mdio0-pins {
+		mux {
+			function = "mdio";
+			groups = "mdc_mdio0";
+		};
+
+		conf {
+			groups = "mdc_mdio0";
+			drive-strength = <MTK_DRIVE_10mA>;
+		};
+	};
+
+	gbe0_led0_pins: gbe0-pins {
+		mux {
+			function = "led";
+			groups = "gbe0_led0";
+		};
+	};
+
+	gbe1_led0_pins: gbe1-pins {
+		mux {
+			function = "led";
+			groups = "gbe1_led0";
+		};
+	};
+
+	gbe2_led0_pins: gbe2-pins {
+		mux {
+			function = "led";
+			groups = "gbe2_led0";
+		};
+	};
+
+	gbe3_led0_pins: gbe3-pins {
+		mux {
+			function = "led";
+			groups = "gbe3_led0";
+		};
+	};
+
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	i2s_pins: i2s-pins {
+		mux {
+			function = "audio";
+			groups = "i2s";
+		};
+	};
+
+	pcm_pins: pcm-pins {
+		mux {
+			function = "audio";
+			groups = "pcm";
+		};
+	};
+
+	uart1_pins: uart1-pins {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins>;
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		mac-type = "xgdm";
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <10000>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		mac-type = "xgdm";
+		phy-mode = "usxgmii";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		mac-type = "xgdm";
+		phy-mode = "usxgmii";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <10500000>;
+
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+					phy-mode = "gmii";
+					phy-handle = <&sphy0>;
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+					phy-mode = "gmii";
+					phy-handle = <&sphy1>;
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+					phy-mode = "gmii";
+					phy-handle = <&sphy2>;
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+					phy-mode = "gmii";
+					phy-handle = <&sphy3>;
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+
+			mdio {
+				compatible = "mediatek,dsa-slave-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sphy0: switch_phy0@0 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <0>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe0_led0_pins>;
+					nvmem-cells = <&phy_calibration_p0>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy1: switch_phy1@1 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <1>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe1_led0_pins>;
+					nvmem-cells = <&phy_calibration_p1>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy2: switch_phy2@2 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <2>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe2_led0_pins>;
+					nvmem-cells = <&phy_calibration_p2>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy3: switch_phy3@3 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <3>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe3_led0_pins>;
+					nvmem-cells = <&phy_calibration_p3>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&slot0 {
+	mt7996@0,0 {
+		reg = <0x0000 0 0 0 0>;
+		device_type = "pci";
+		mediatek,mtd-eeprom = <&factory 0x0>;
+	};
+};
+
+&slot1 {
+	mt7992@0,0 {
+		reg = <0x0000 0 0 0 0>;
+		device_type = "pci";
+		mediatek,mtd-eeprom = <&factory 0x0>;
+	};
+};
+
+&wmcpu_emi{
+	reg = <0 0x50000000 0 0x00A00000>;
+};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
new file mode 100644
index 0000000..9f3bb0f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
@@ -0,0 +1,540 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988D DSA 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-spim-snand-CASAN",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	cpus {
+		/delete-node/ cpu@3;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	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 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x7080000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	sound_wm8960 {
+		compatible = "mediatek,mt79xx-wm8960-machine";
+		mediatek,platform = <&afe>;
+		audio-routing = "Headphone", "HP_L",
+				"Headphone", "HP_R",
+				"LINPUT1", "AMIC",
+				"RINPUT1", "AMIC";
+		mediatek,audio-codec = <&wm8960>;
+		status = "disabled";
+	};
+
+	sound_si3218x {
+		compatible = "mediatek,mt79xx-si3218x-machine";
+		mediatek,platform = <&afe>;
+		mediatek,ext-codec = <&proslic_spi>;
+		status = "disabled";
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&afe {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcm_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	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;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+
+	wm8960: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+	};
+};
+
+&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";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+
+	proslic_spi: proslic_spi@0 {
+		compatible = "silabs,proslic_spi";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+		spi-cpha = <1>;
+		spi-cpol = <1>;
+		channel_count = <1>;
+		debug_level = <4>;       /* 1 = TRC, 2 = DBG, 4 = ERR */
+		reset_gpio = <&pio 54 0>;
+		ig,enable-spi = <1>;     /* 1: Enable, 0: Disable */
+	};
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "disabled";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	mdio0_pins: mdio0-pins {
+		mux {
+			function = "mdio";
+			groups = "mdc_mdio0";
+		};
+
+		conf {
+			groups = "mdc_mdio0";
+			drive-strength = <MTK_DRIVE_10mA>;
+		};
+	};
+
+	gbe0_led0_pins: gbe0-pins {
+		mux {
+			function = "led";
+			groups = "gbe0_led0";
+		};
+	};
+
+	gbe1_led0_pins: gbe1-pins {
+		mux {
+			function = "led";
+			groups = "gbe1_led0";
+		};
+	};
+
+	gbe2_led0_pins: gbe2-pins {
+		mux {
+			function = "led";
+			groups = "gbe2_led0";
+		};
+	};
+
+	gbe3_led0_pins: gbe3-pins {
+		mux {
+			function = "led";
+			groups = "gbe3_led0";
+		};
+	};
+
+	i2p5gbe_led0_pins: 2p5gbe-pins {
+		mux {
+			function = "led";
+			groups = "2p5gbe_led0";
+		};
+	};
+
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	i2s_pins: i2s-pins {
+		mux {
+			function = "audio";
+			groups = "i2s";
+		};
+	};
+
+	pcm_pins: pcm-pins {
+		mux {
+			function = "audio";
+			groups = "pcm";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins>;
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		mac-type = "xgdm";
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <10000>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		mac-type = "xgdm";
+		phy-mode = "xgmii";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		mac-type = "xgdm";
+		phy-mode = "usxgmii";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <10500000>;
+
+		phy0: ethernet-phy@0 {
+			pinctrl-names = "i2p5gbe-led";
+			pinctrl-0 = <&i2p5gbe_led0_pins>;
+			reg = <15>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			phy-mode = "xgmii";
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 3 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+					phy-mode = "gmii";
+					phy-handle = <&sphy0>;
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+					phy-mode = "gmii";
+					phy-handle = <&sphy1>;
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+					phy-mode = "gmii";
+					phy-handle = <&sphy2>;
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+					phy-mode = "gmii";
+					phy-handle = <&sphy3>;
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+
+			mdio {
+				compatible = "mediatek,dsa-slave-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sphy0: switch_phy0@0 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <0>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe0_led0_pins>;
+					nvmem-cells = <&phy_calibration_p0>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy1: switch_phy1@1 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <1>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe1_led0_pins>;
+					nvmem-cells = <&phy_calibration_p1>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy2: switch_phy2@2 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <2>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe2_led0_pins>;
+					nvmem-cells = <&phy_calibration_p2>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy3: switch_phy3@3 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <3>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe3_led0_pins>;
+					nvmem-cells = <&phy_calibration_p3>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&slot0 {
+	mt7996@0,0 {
+		reg = <0x0000 0 0 0 0>;
+		device_type = "pci";
+		mediatek,mtd-eeprom = <&factory 0x0>;
+	};
+};
+
+&wmcpu_emi{
+	reg = <0 0x50000000 0 0x00A00000>;
+};
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 c679247..6cf9fc5 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
@@ -3898,7 +3898,12 @@
 	/* FE int grouping */
 	mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp);
 	mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->qdma.int_grp2);
-	mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT))
+		mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
+	else {
+		mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->pdma.int_grp);
+		mtk_w32(eth, 0x210F2FF3, MTK_FE_INT_GRP);
+	}
 	mtk_w32(eth, MTK_FE_INT_TSO_FAIL |
 		MTK_FE_INT_TSO_ILLEGAL | MTK_FE_INT_TSO_ALIGN |
 		MTK_FE_INT_RFIFO_OV | MTK_FE_INT_RFIFO_UF, MTK_FE_INT_ENABLE);
@@ -5035,15 +5040,19 @@
 		}
 	}
 
-	for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
-		eth->irq_pdma[i] = platform_get_irq(pdev, i);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+		for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
+			eth->irq_pdma[i] = platform_get_irq(pdev, i);
+	}
 
 	for (i = 0; i < MTK_FE_IRQ_NUM; i++) {
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
 			eth->irq_fe[i] = eth->irq_fe[0];
-		else
+		else if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT))
 			eth->irq_fe[i] =
 				platform_get_irq(pdev, i + MTK_PDMA_IRQ_NUM);
+		else
+			eth->irq_fe[i] = platform_get_irq(pdev, i);
 
 		if (eth->irq_fe[i] < 0) {
 			dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
@@ -5125,39 +5134,55 @@
 		if (err)
 			goto err_free_dev;
 
-		err = devm_request_irq(eth->dev, eth->irq_fe[2],
-				       mtk_handle_fe_irq, 0,
-				       dev_name(eth->dev), eth);
-		if (err)
-			goto err_free_dev;
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+			err = devm_request_irq(eth->dev, eth->irq_fe[2],
+					       mtk_handle_fe_irq, 0,
+					       dev_name(eth->dev), eth);
+			if (err)
+				goto err_free_dev;
 
-		err = devm_request_irq(eth->dev, eth->irq_pdma[0],
-				       mtk_handle_irq_rx, IRQF_SHARED,
-				       dev_name(eth->dev), &eth->rx_napi[0]);
-		if (err)
-			goto err_free_dev;
+			err = devm_request_irq(eth->dev, eth->irq_pdma[0],
+					       mtk_handle_irq_rx, IRQF_SHARED,
+					       dev_name(eth->dev), &eth->rx_napi[0]);
+			if (err)
+				goto err_free_dev;
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-			for (i = 0; i < MTK_RX_RSS_NUM; i++) {
-				err = devm_request_irq(eth->dev,
-						       eth->irq_pdma[MTK_RSS_RING(i)],
-						       mtk_handle_irq_rx, IRQF_SHARED,
-						       dev_name(eth->dev),
-						       &eth->rx_napi[MTK_RSS_RING(i)]);
-				if (err)
-					goto err_free_dev;
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+				for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+					err = devm_request_irq(eth->dev,
+							       eth->irq_pdma[MTK_RSS_RING(i)],
+							       mtk_handle_irq_rx, IRQF_SHARED,
+							       dev_name(eth->dev),
+							       &eth->rx_napi[MTK_RSS_RING(i)]);
+					if (err)
+						goto err_free_dev;
+				}
 			}
-		}
+
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+				i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2) ||
+				     MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) ? 0 : 1;
+				for (; i < MTK_HW_LRO_RING_NUM; i++) {
+					err = devm_request_irq(eth->dev,
+							       eth->irq_pdma[i],
+							       mtk_handle_irq_rx, IRQF_SHARED,
+							       dev_name(eth->dev),
+							       &eth->rx_napi[MTK_HW_LRO_RING(i)]);
+					if (err)
+						goto err_free_dev;
+				}
+			}
+		} else {
+			err = devm_request_irq(eth->dev, eth->irq_fe[2],
+					       mtk_handle_irq_rx, 0,
+					       dev_name(eth->dev), &eth->rx_napi[0]);
+			if (err)
+				goto err_free_dev;
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
-			i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2) ||
-			     MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) ? 0 : 1;
-			for (; i < MTK_HW_LRO_RING_NUM; i++) {
-				err = devm_request_irq(eth->dev,
-						       eth->irq_pdma[i],
-						       mtk_handle_irq_rx, IRQF_SHARED,
-						       dev_name(eth->dev),
-						       &eth->rx_napi[MTK_HW_LRO_RING(i)]);
+			if (MTK_FE_IRQ_NUM > 3) {
+				err = devm_request_irq(eth->dev, eth->irq_fe[3],
+						       mtk_handle_fe_irq, 0,
+						       dev_name(eth->dev), eth);
 				if (err)
 					goto err_free_dev;
 			}
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 0e658b0..7811de7 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
@@ -92,7 +92,11 @@
 #define MTK_FE_INT_RFIFO_UF	BIT(19)
 #define MTK_GDM1_AF		BIT(28)
 #define MTK_GDM2_AF		BIT(29)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_FE_IRQ_NUM		(4)
+#else
+#define MTK_FE_IRQ_NUM		(3)
+#endif
 #define MTK_PDMA_IRQ_NUM	(4)
 #define MTK_MAX_IRQ_NUM		(MTK_FE_IRQ_NUM + MTK_PDMA_IRQ_NUM)
 
@@ -1396,6 +1400,7 @@
 	MTK_HWLRO_BIT,
 	MTK_RSS_BIT,
 	MTK_SHARED_INT_BIT,
+	MTK_PDMA_INT_BIT,
 	MTK_TRGMII_MT7621_CLK_BIT,
 	MTK_QDMA_BIT,
 	MTK_NETSYS_V1_BIT,
@@ -1447,6 +1452,7 @@
 #define MTK_HWLRO		BIT_ULL(MTK_HWLRO_BIT)
 #define MTK_RSS			BIT_ULL(MTK_RSS_BIT)
 #define MTK_SHARED_INT		BIT_ULL(MTK_SHARED_INT_BIT)
+#define MTK_PDMA_INT		BIT_ULL(MTK_PDMA_INT_BIT)
 #define MTK_TRGMII_MT7621_CLK	BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT)
 #define MTK_QDMA		BIT_ULL(MTK_QDMA_BIT)
 #define MTK_NETSYS_V1		BIT_ULL(MTK_NETSYS_V1_BIT)
@@ -1556,17 +1562,17 @@
 		      MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 | \
 		      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
 
-#define MT7986_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+#define MT7986_CAPS   (MTK_PDMA_INT | MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
                        MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
-			MTK_NETSYS_V2 | MTK_RSS)
+		       MTK_NETSYS_V2 | MTK_RSS)
 
-#define MT7981_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
-			MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
-			MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
-			MTK_NETSYS_V2 | MTK_RSS)
+#define MT7981_CAPS   (MTK_PDMA_INT | MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+		       MTK_GMAC2_GEPHY | MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
+		       MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
+		       MTK_NETSYS_V2 | MTK_RSS)
 
 #define MT7988_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII | \
-		       MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA | \
+		       MTK_PDMA_INT | MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA | \
 		       MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | \
 		       MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
 		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index f575f1b..2ce7495 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -411,10 +411,6 @@
 	hnat_priv->g_ppdev = dev_get_by_name(&init_net, hnat_priv->ppd);
 	hnat_priv->g_wandev = dev_get_by_name(&init_net, hnat_priv->wan);
 
-	if (hnat_priv->data->version == MTK_HNAT_V3) {
-		cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, TSID_EN, 1);
-		cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, DSCP_TRFC_ECN_EN, 1);
-	}
 	dev_info(hnat_priv->dev, "PPE%d hwnat start\n", ppe_id);
 
 	spin_lock_init(&hnat_priv->entry_lock);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index d770db5..8f11a83 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -1219,10 +1219,11 @@
 #define UDF_HNAT_PRE_FILLED BIT(4)
 
 #if defined(CONFIG_MEDIATEK_NETSYS_V3)
-#define TPORT_FLAG(dev, skb)				\
+#define TPORT_FLAG(dev, skb, qid)			\
 	((IS_HQOS_UL_MODE && IS_WAN(dev)) ||		\
 	 (IS_HQOS_DL_MODE && IS_LAN_GRP(dev)) ||	\
-	 (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)))
+	 (IS_PPPQ_MODE && (IS_PPPQ_PATH(dev, skb) ||	\
+			   qid >= MAX_PPPQ_PORT_NUM)))
 #endif
 
 extern const struct of_device_id of_hnat_match[];
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 fc7d216..f6c6499 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
@@ -317,6 +317,8 @@
 	pr_info("              3   <entry_idx>  Delete PPE0 specific foe entry of assigned <entry_idx>\n");
 	pr_info("              4   <entry_idx>  Show PPE1 specific foe entry info. of assigned <entry_idx>\n");
 	pr_info("              5   <entry_idx>  Delete PPE1 specific foe entry of assigned <entry_idx>\n");
+	pr_info("              6   <entry_idx>  Show PPE2 specific foe entry info. of assigned <entry_idx>\n");
+	pr_info("              7   <entry_idx>  Delete PPE2 specific foe entry of assigned <entry_idx>\n");
 	pr_info("                               When entry_idx is -1, clear all entries\n");
 
 	return 0;
@@ -333,16 +335,24 @@
 	return 0;
 }
 
-int wrapped_ppe0_entry_detail(int index) {
+int wrapped_ppe0_entry_detail(int index)
+{
 	entry_detail(0, index);
 	return 0;
 }
 
-int wrapped_ppe1_entry_detail(int index) {
+int wrapped_ppe1_entry_detail(int index)
+{
 	entry_detail(1, index);
 	return 0;
 }
 
+int wrapped_ppe2_entry_detail(int index)
+{
+	entry_detail(2, index);
+	return 0;
+}
+
 int entry_detail(u32 ppe_id, int index)
 {
 	struct foe_entry *entry;
@@ -646,16 +656,24 @@
 	return 0;
 }
 
-int wrapped_ppe0_entry_delete(int index) {
+int wrapped_ppe0_entry_delete(int index)
+{
 	entry_delete(0, index);
 	return 0;
 }
 
-int wrapped_ppe1_entry_delete(int index) {
+int wrapped_ppe1_entry_delete(int index)
+{
 	entry_delete(1, index);
 	return 0;
 }
 
+int wrapped_ppe2_entry_delete(int index)
+{
+	entry_delete(2, index);
+	return 0;
+}
+
 int entry_delete(u32 ppe_id, int index)
 {
 	struct foe_entry *entry;
@@ -825,6 +843,8 @@
 	[3] = wrapped_ppe0_entry_delete,
 	[4] = wrapped_ppe1_entry_detail,
 	[5] = wrapped_ppe1_entry_delete,
+	[6] = wrapped_ppe2_entry_detail,
+	[7] = wrapped_ppe2_entry_delete,
 };
 
 static const debugfs_write_func cr_set_func[] = {
@@ -1735,6 +1755,8 @@
 	case 3:
 	case 4:
 	case 5:
+	case 6:
+	case 7:
 		p_token = strsep(&p_buf, p_delimiter);
 		if (!p_token)
 			arg1 = 0;
@@ -2674,6 +2696,7 @@
 	struct mtk_hnat *h = hnat_priv;
 	u32 cfg;
 
+	cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
 	if (enable) {
 		cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
 		cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
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 85c38e0..7af79ee 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
@@ -211,11 +211,13 @@
 
 static void gmac_ppe_fwd_enable(struct net_device *dev)
 {
+	struct mtk_mac *mac = netdev_priv(dev);
+
 	if (IS_LAN(dev) || IS_GMAC1_MODE)
 		set_gmac_ppe_fwd(NR_GMAC1_PORT, 1);
-	else if (IS_WAN(dev))
+	else if (mac->id == MTK_GMAC2_ID)
 		set_gmac_ppe_fwd(NR_GMAC2_PORT, 1);
-	else if (IS_LAN2(dev))
+	else if (mac->id == MTK_GMAC3_ID)
 		set_gmac_ppe_fwd(NR_GMAC3_PORT, 1);
 }
 
@@ -1220,6 +1222,7 @@
 	u32 qid = 0;
 	u32 port_id = 0;
 	int mape = 0;
+	struct mtk_mac *mac = netdev_priv(dev);
 
 	ct = nf_ct_get(skb, &ctinfo);
 
@@ -1694,7 +1697,7 @@
 		else
 			gmac = NR_GMAC1_PORT;
 	} else if (IS_LAN2(dev)) {
-		gmac = NR_GMAC3_PORT;
+		gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
 	} else if (IS_WAN(dev)) {
 		if (IS_DSA_WAN(dev))
 			port_id = hnat_dsa_fill_stag(dev,&entry, hw_path,
@@ -1706,7 +1709,10 @@
 			entry.ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
 			entry.ipv4_hnapt.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
 		} else {
-			gmac = (IS_GMAC1_MODE) ? NR_GMAC1_PORT : NR_GMAC2_PORT;
+			if (IS_GMAC1_MODE)
+				gmac = NR_GMAC1_PORT;
+			else
+				gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
 		}
 	} else if (IS_EXT(dev) && (FROM_GE_PPD(skb) || FROM_GE_LAN_GRP(skb) ||
 		   FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb) || FROM_WED(skb))) {
@@ -1775,17 +1781,12 @@
 			}
 
 			if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT ||
-			    (IS_PPPQ_MODE && !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
+			    (IS_PPPQ_MODE && (qid < MAX_PPPQ_PORT_NUM) &&
+			     !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
 				entry.ipv4_hnapt.iblk2.fqos = 0;
 			else
 #if defined(CONFIG_MEDIATEK_NETSYS_V3)
-				if ((IS_HQOS_UL_MODE && IS_WAN(dev)) ||
-				    (IS_HQOS_DL_MODE && IS_LAN_GRP(dev)) ||
-				    (IS_PPPQ_MODE &&
-				     IS_PPPQ_PATH(dev, skb)))
-					entry.ipv4_hnapt.tport_id = 1;
-				else
-					entry.ipv4_hnapt.tport_id = 0;
+				entry.ipv4_hnapt.tport_id = TPORT_FLAG(dev, skb, qid) ? 1 : 0;
 #else
 				entry.ipv4_hnapt.iblk2.fqos =
 					(!IS_PPPQ_MODE ||
@@ -1821,21 +1822,25 @@
 			}
 
 			if (FROM_EXT(skb) ||
-			    (IS_PPPQ_MODE && !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
+			    (IS_PPPQ_MODE && (qid < MAX_PPPQ_PORT_NUM) &&
+			     !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
 				entry.ipv6_5t_route.iblk2.fqos = 0;
 			else
 #if defined(CONFIG_MEDIATEK_NETSYS_V3)
 				switch (foe->bfib1.pkt_type) {
 				case IPV4_MAP_E:
 				case IPV4_MAP_T:
-					entry.ipv4_mape.tport_id = TPORT_FLAG(dev, skb) ? 1 : 0;
+					entry.ipv4_mape.tport_id =
+						TPORT_FLAG(dev, skb, qid) ? 1 : 0;
 					break;
 				case IPV6_HNAPT:
 				case IPV6_HNAT:
-					entry.ipv6_hnapt.tport_id = TPORT_FLAG(dev, skb) ? 1 : 0;
+					entry.ipv6_hnapt.tport_id =
+						TPORT_FLAG(dev, skb, qid) ? 1 : 0;
 					break;
 				default:
-					entry.ipv6_5t_route.tport_id = TPORT_FLAG(dev, skb) ? 1 : 0;
+					entry.ipv6_5t_route.tport_id =
+						TPORT_FLAG(dev, skb, qid) ? 1 : 0;
 					break;
 				}
 #else
@@ -2313,15 +2318,20 @@
 	switch (ntohs(eth->h_proto)) {
 	case ETH_P_IP:
 		iph = ip_hdr(skb);
-		if (IS_IPV4_GRP(entry) && entry->ipv4_hnapt.iblk2.dscp != iph->tos)
+		if (IS_IPV4_GRP(entry) && entry->ipv4_hnapt.iblk2.dscp != iph->tos) {
+			entry->ipv4_hnapt.iblk2.dscp = iph->tos;
 			flag = true;
+		}
 		break;
 	case ETH_P_IPV6:
 		ip6h = ipv6_hdr(skb);
 		if ((IS_IPV6_3T_ROUTE(entry) || IS_IPV6_5T_ROUTE(entry)) &&
 			(entry->ipv6_5t_route.iblk2.dscp !=
-			(ip6h->priority << 4 | (ip6h->flow_lbl[0] >> 4))))
+			(ip6h->priority << 4 | (ip6h->flow_lbl[0] >> 4)))) {
+			entry->ipv6_5t_route.iblk2.dscp =
+				(ip6h->priority << 4 | (ip6h->flow_lbl[0] >> 4));
 			flag = true;
+		}
 		break;
 	default:
 		return;
@@ -2329,9 +2339,8 @@
 
 	if (flag) {
 		if (debug_level >= 7)
-			pr_info("%s %d Delete entry idx=%d\n", __func__, __LINE__,
+			pr_info("%s %d update entry idx=%d\n", __func__, __LINE__,
 			skb_hnat_entry(skb));
-		memset(entry, 0, sizeof(struct foe_entry));
 		hnat_cache_ebl(1);
 	}
 }
@@ -2705,8 +2714,7 @@
 			break;
 
 		/* update dscp for qos */
-		if (hnat_priv->data->version != MTK_HNAT_V3)
-			mtk_hnat_dscp_update(skb, entry);
+		mtk_hnat_dscp_update(skb, entry);
 
 		/* update mcast timestamp*/
 		if (hnat_priv->data->version == MTK_HNAT_V1_3 &&
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 8cbe4ac..6a1c9e0 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
@@ -253,8 +253,8 @@
 		.get_rate_matching	= mt798x_2p5ge_phy_get_rate_matching,
 		//.config_intr	= genphy_no_config_intr,
 		//.handle_interrupt = genphy_no_ack_interrupt,
-		//.suspend	= genphy_suspend,
-		//.resume		= genphy_resume,
+		.suspend	= genphy_suspend,
+		.resume		= genphy_resume,
 	},
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
index 4012dba..d2c86ac 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -53,6 +53,7 @@
 #define PCIE_LINK_STATUS_REG		0x154
 #define PCIE_PORT_LINKUP		BIT(8)
 
+#define PCIE_MSI_GROUP_NUM		4
 #define PCIE_MSI_SET_NUM		8
 #define PCIE_MSI_IRQS_PER_SET		32
 #define PCIE_MSI_IRQS_NUM \
@@ -75,6 +76,12 @@
 #define PCIE_MSI_SET_ENABLE_OFFSET	0x08
 #define PCIE_MSI_SET_GRP1_ENABLE_OFFSET	0x0c
 
+#define PCIE_MSI_SET_GRP2_ENABLE_OFFSET	0x1c0
+#define PCIE_MSI_SET_GRP2_OFFSET	0x04
+
+#define PCIE_MSI_SET_GRP3_ENABLE_OFFSET	0x1e0
+#define PCIE_MSI_SET_GRP3_OFFSET	0x04
+
 #define PCIE_MSI_SET_ADDR_HI_BASE	0xc80
 #define PCIE_MSI_SET_ADDR_HI_OFFSET	0x04
 
@@ -100,18 +107,44 @@
 #define PCIE_ATR_TLP_TYPE_IO		PCIE_ATR_TLP_TYPE(2)
 
 /**
+ * enum mtk_msi_group_type - PCIe controller MSI group type
+ * @group0_merge_msi: all MSI are merged to group0
+ * @group1_direct_msi: all MSI have independent IRQs via group1
+ * @group_binding_msi: all MSI are bound to all group
+ */
+enum mtk_msi_group_type {
+	group0_merge_msi,
+	group1_direct_msi,
+	group_binding_msi,
+};
+
+/**
  * struct mtk_msi_set - MSI information for each set
  * @base: IO mapped register base
+ * @enable: IO mapped enable register address
  * @msg_addr: MSI message address
  * @saved_irq_state: IRQ enable state saved at suspend time
  */
 struct mtk_msi_set {
 	void __iomem *base;
+	void __iomem *enable[PCIE_MSI_GROUP_NUM];
 	phys_addr_t msg_addr;
-	u32 saved_irq_state;
+	u32 saved_irq_state[PCIE_MSI_GROUP_NUM];
 };
 
 /**
+ * struct mtk_pcie_irq - PCIe controller interrupt information
+ * @irq: IRQ interrupt number
+ * @group: IRQ MSI group number
+ * @mapped_table: IRQ MSI group mapped table
+ */
+struct mtk_pcie_irq {
+	int irq;
+	int group;
+	u32 mapped_table;
+};
+
+/**
  * struct mtk_pcie_port - PCIe port information
  * @dev: pointer to PCIe device
  * @base: IO mapped register base
@@ -121,13 +154,17 @@
  * @phy: PHY controller block
  * @clks: PCIe clocks
  * @num_clks: PCIe clocks count for this port
+ * @max_link_width: PCIe slot max supported link width
  * @irq: PCIe controller interrupt number
+ * @num_irqs: PCIe irqs count
+ * @irqs: PCIe controller interrupts information
  * @saved_irq_state: IRQ enable state saved at suspend time
  * @irq_lock: lock protecting IRQ register access
  * @intx_domain: legacy INTx IRQ domain
  * @msi_domain: MSI IRQ domain
  * @msi_bottom_domain: MSI IRQ bottom domain
  * @msi_sets: MSI sets information
+ * @msi_group_type: PCIe controller MSI group type
  * @lock: lock protecting IRQ bit map
  * @msi_irq_in_use: bit map for assigned MSI IRQ
  */
@@ -140,17 +177,18 @@
 	struct phy *phy;
 	struct clk_bulk_data *clks;
 	int num_clks;
+	int max_link_width;
 
 	int irq;
-	int max_link_width;
-	int direct_msi_enable;
-	int direct_msi[PCIE_MSI_IRQS_PER_SET];
+	int num_irqs;
+	struct mtk_pcie_irq *irqs;
 	u32 saved_irq_state;
 	raw_spinlock_t irq_lock;
 	struct irq_domain *intx_domain;
 	struct irq_domain *msi_domain;
 	struct irq_domain *msi_bottom_domain;
 	struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM];
+	enum mtk_msi_group_type msi_group_type;
 	struct mutex lock;
 	DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
 };
@@ -271,14 +309,23 @@
 
 static void mtk_pcie_enable_msi(struct mtk_pcie_port *port)
 {
+	void __iomem *base = port->base + PCIE_MSI_SET_BASE_REG;
 	int i;
 	u32 val;
 
 	for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
 		struct mtk_msi_set *msi_set = &port->msi_sets[i];
 
-		msi_set->base = port->base + PCIE_MSI_SET_BASE_REG +
-				i * PCIE_MSI_SET_OFFSET;
+		msi_set->base = base + i * PCIE_MSI_SET_OFFSET;
+		msi_set->enable[0] = base + PCIE_MSI_SET_ENABLE_OFFSET +
+				     i * PCIE_MSI_SET_OFFSET;
+		msi_set->enable[1] = base + PCIE_MSI_SET_GRP1_ENABLE_OFFSET +
+				     i * PCIE_MSI_SET_OFFSET;
+		msi_set->enable[2] = base + PCIE_MSI_SET_GRP2_ENABLE_OFFSET +
+				     i * PCIE_MSI_SET_GRP2_OFFSET;
+		msi_set->enable[3] = base + PCIE_MSI_SET_GRP3_ENABLE_OFFSET +
+				     i * PCIE_MSI_SET_GRP3_OFFSET;
+
 		msi_set->msg_addr = port->reg_base + PCIE_MSI_SET_BASE_REG +
 				    i * PCIE_MSI_SET_OFFSET;
 
@@ -293,11 +340,9 @@
 	val |= PCIE_MSI_SET_ENABLE;
 	writel_relaxed(val, port->base + PCIE_MSI_SET_ENABLE_REG);
 
-	if (!port->direct_msi_enable) {
-		val = readl_relaxed(port->base + PCIE_INT_ENABLE_REG);
-		val |= PCIE_MSI_ENABLE;
-		writel_relaxed(val, port->base + PCIE_INT_ENABLE_REG);
-	}
+	val = readl_relaxed(port->base + PCIE_INT_ENABLE_REG);
+	val |= PCIE_MSI_ENABLE;
+	writel_relaxed(val, port->base + PCIE_INT_ENABLE_REG);
 }
 
 static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
@@ -399,18 +444,44 @@
 	return 0;
 }
 
+static struct mtk_pcie_irq *mtk_msi_hwirq_get_irqs(struct mtk_pcie_port *port, unsigned long hwirq)
+{
+	int i;
+
+	for (i = 0; i < port->num_irqs; i++)
+		if (port->irqs[i].mapped_table & BIT(hwirq))
+			return &port->irqs[i];
+
+	return NULL;
+}
+
+static struct mtk_pcie_irq *mtk_msi_irq_get_irqs(struct mtk_pcie_port *port, unsigned int irq)
+{
+	int i;
+
+	for (i = 0; i < port->num_irqs; i++)
+		if (port->irqs[i].irq == irq)
+			return &port->irqs[i];
+
+	return NULL;
+}
+
-static int mtk_pcie_set_msi_affinity(struct irq_data *data,
+static int mtk_pcie_msi_set_affinity(struct irq_data *data,
 				 const struct cpumask *mask, bool force)
 {
 	struct mtk_pcie_port *port = data->domain->host_data;
 	struct irq_data *port_data;
 	struct irq_chip *port_chip;
-	int msi_bit, irq, ret;
+	struct mtk_pcie_irq *irqs;
+	unsigned long hwirq;
+	int ret;
 
-	msi_bit = data->hwirq % PCIE_MSI_IRQS_PER_SET;
-	irq = port->direct_msi[msi_bit];
+	hwirq = data->hwirq % PCIE_MSI_IRQS_PER_SET;
+	irqs = mtk_msi_hwirq_get_irqs(port, hwirq);
+	if (IS_ERR_OR_NULL(irqs))
+		return -EINVAL;
 
-	port_data = irq_get_irq_data(irq);
+	port_data = irq_get_irq_data(irqs->irq);
 	port_chip = irq_data_get_irq_chip(port_data);
 	if (!port_chip || !port_chip->irq_set_affinity)
 		return -EINVAL;
@@ -422,12 +493,6 @@
 	return ret;
 }
 
-static int mtk_pcie_set_affinity(struct irq_data *data,
-				 const struct cpumask *mask, bool force)
-{
-	return -EINVAL;
-}
-
 static void mtk_pcie_msi_irq_mask(struct irq_data *data)
 {
 	pci_msi_mask_irq(data);
@@ -482,23 +547,19 @@
 {
 	struct mtk_msi_set *msi_set = irq_data_get_irq_chip_data(data);
 	struct mtk_pcie_port *port = data->domain->host_data;
+	struct mtk_pcie_irq *irqs;
 	unsigned long hwirq, flags;
 	u32 val;
 
 	hwirq =	data->hwirq % PCIE_MSI_IRQS_PER_SET;
+	irqs = mtk_msi_hwirq_get_irqs(port, hwirq);
+	if (IS_ERR_OR_NULL(irqs))
+		return;
 
 	raw_spin_lock_irqsave(&port->irq_lock, flags);
-	if (port->direct_msi_enable) {
-		val = readl_relaxed(msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-		val &= ~BIT(hwirq);
-		writel_relaxed(val, msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-	} else {
-		val = readl_relaxed(msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
-		val &= ~BIT(hwirq);
-		writel_relaxed(val, msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
-	}
+	val = readl_relaxed(msi_set->enable[irqs->group]);
+	val &= ~BIT(hwirq);
+	writel_relaxed(val, msi_set->enable[irqs->group]);
 	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
 }
 
@@ -506,23 +567,19 @@
 {
 	struct mtk_msi_set *msi_set = irq_data_get_irq_chip_data(data);
 	struct mtk_pcie_port *port = data->domain->host_data;
+	struct mtk_pcie_irq *irqs;
 	unsigned long hwirq, flags;
 	u32 val;
 
 	hwirq =	data->hwirq % PCIE_MSI_IRQS_PER_SET;
+	irqs = mtk_msi_hwirq_get_irqs(port, hwirq);
+	if (IS_ERR_OR_NULL(irqs))
+		return;
 
 	raw_spin_lock_irqsave(&port->irq_lock, flags);
-	if (port->direct_msi_enable) {
-		val = readl_relaxed(msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-		val |= BIT(hwirq);
-		writel_relaxed(val, msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-	} else {
-		val = readl_relaxed(msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
-		val |= BIT(hwirq);
-		writel_relaxed(val, msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
-	}
+	val = readl_relaxed(msi_set->enable[irqs->group]);
+	val |= BIT(hwirq);
+	writel_relaxed(val, msi_set->enable[irqs->group]);
 	raw_spin_unlock_irqrestore(&port->irq_lock, flags);
 }
 
@@ -531,7 +588,7 @@
 	.irq_mask		= mtk_msi_bottom_irq_mask,
 	.irq_unmask		= mtk_msi_bottom_irq_unmask,
 	.irq_compose_msi_msg	= mtk_compose_msi_msg,
-	.irq_set_affinity	= mtk_pcie_set_affinity,
+	.irq_set_affinity	= mtk_pcie_msi_set_affinity,
 	.name			= "MSI",
 };
 
@@ -628,11 +685,28 @@
 	writel_relaxed(BIT(hwirq), port->base + PCIE_INT_STATUS_REG);
 }
 
+static int mtk_pcie_intx_set_affinity(struct irq_data *data,
+				 const struct cpumask *mask, bool force)
+{
+	struct mtk_pcie_port *port = data->domain->host_data;
+	struct irq_data *port_data;
+	struct irq_chip *port_chip;
+	int ret;
+
+	port_data = irq_get_irq_data(port->irq);
+	port_chip = irq_data_get_irq_chip(port_data);
+	if (!port_chip || !port_chip->irq_set_affinity)
+		return -EINVAL;
+	ret = port_chip->irq_set_affinity(port_data, mask, force);
+	irq_data_update_effective_affinity(data, mask);
+	return ret;
+}
+
 static struct irq_chip mtk_intx_irq_chip = {
 	.irq_mask		= mtk_intx_mask,
 	.irq_unmask		= mtk_intx_unmask,
 	.irq_eoi		= mtk_intx_eoi,
-	.irq_set_affinity	= mtk_pcie_set_affinity,
+	.irq_set_affinity	= mtk_pcie_intx_set_affinity,
 	.name			= "INTx",
 };
 
@@ -691,11 +765,6 @@
 		goto err_msi_domain;
 	}
 
-	if (of_find_property(node, "direct_msi", NULL))
-		port->direct_msi_enable = true;
-	else
-		port->direct_msi_enable = false;
-
 	return 0;
 
 err_msi_domain:
@@ -708,7 +777,10 @@
 
 static void mtk_pcie_irq_teardown(struct mtk_pcie_port *port)
 {
-	irq_set_chained_handler_and_data(port->irq, NULL, NULL);
+	int i;
+
+	for (i = 0; i < port->num_irqs; i++)
+		irq_set_chained_handler_and_data(port->irqs[i].irq, NULL, NULL);
 
 	if (port->intx_domain)
 		irq_domain_remove(port->intx_domain);
@@ -719,17 +791,27 @@
 	if (port->msi_bottom_domain)
 		irq_domain_remove(port->msi_bottom_domain);
 
-	irq_dispose_mapping(port->irq);
+	for (i = 0; i < port->num_irqs; i++)
+		irq_dispose_mapping(port->irqs[i].irq);
 }
 
-static void mtk_pcie_msi_handler(struct mtk_pcie_port *port, int set_idx)
+static void mtk_pcie_msi_handler(struct irq_desc *desc, int set_idx)
 {
+	struct mtk_pcie_port *port = irq_desc_get_handler_data(desc);
 	struct mtk_msi_set *msi_set = &port->msi_sets[set_idx];
+	struct mtk_pcie_irq *irqs;
 	unsigned long msi_enable, msi_status;
 	unsigned int virq;
 	irq_hw_number_t bit, hwirq;
 
-	msi_enable = readl_relaxed(msi_set->base + PCIE_MSI_SET_ENABLE_OFFSET);
+	irqs = mtk_msi_irq_get_irqs(port, irq_desc_get_irq(desc));
+	if (IS_ERR_OR_NULL(irqs))
+		return;
+
+	msi_enable = readl_relaxed(msi_set->enable[irqs->group]);
+	msi_enable &= irqs->mapped_table;
+	if (!msi_enable)
+		return;
 
 	do {
 		msi_status = readl_relaxed(msi_set->base +
@@ -752,11 +834,14 @@
 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
 	unsigned long status;
 	unsigned int virq;
-	irq_hw_number_t irq_bit = PCIE_INTX_SHIFT;
+	irq_hw_number_t irq_bit;
 
 	chained_irq_enter(irqchip, desc);
 
 	status = readl_relaxed(port->base + PCIE_INT_STATUS_REG);
+
+	/* INTx handler */
+	irq_bit = PCIE_INTX_SHIFT;
 	for_each_set_bit_from(irq_bit, &status, PCI_NUM_INTX +
 			      PCIE_INTX_SHIFT) {
 		virq = irq_find_mapping(port->intx_domain,
@@ -764,56 +849,85 @@
 		generic_handle_irq(virq);
 	}
 
-	irq_bit = PCIE_MSI_SHIFT;
-	for_each_set_bit_from(irq_bit, &status, PCIE_MSI_SET_NUM +
-			      PCIE_MSI_SHIFT) {
-		mtk_pcie_msi_handler(port, irq_bit - PCIE_MSI_SHIFT);
+	/* Group MSI don't trigger INT_STATUS, need to check MSI_SET_STATUS */
+	if (port->msi_group_type == group0_merge_msi) {
+		irq_bit = PCIE_MSI_SHIFT;
+		for_each_set_bit_from(irq_bit, &status, PCIE_MSI_SET_NUM +
+				      PCIE_MSI_SHIFT) {
+			mtk_pcie_msi_handler(desc, irq_bit - PCIE_MSI_SHIFT);
 
-		writel_relaxed(BIT(irq_bit), port->base + PCIE_INT_STATUS_REG);
+			writel_relaxed(BIT(irq_bit), port->base +
+				       PCIE_INT_STATUS_REG);
+		}
+	} else {
+		for (irq_bit = PCIE_MSI_SHIFT; irq_bit < (PCIE_MSI_SET_NUM +
+		     PCIE_MSI_SHIFT); irq_bit++) {
+			mtk_pcie_msi_handler(desc, irq_bit - PCIE_MSI_SHIFT);
+
+			writel_relaxed(BIT(irq_bit), port->base +
+				       PCIE_INT_STATUS_REG);
+		}
 	}
 
 	chained_irq_exit(irqchip, desc);
 }
 
-static void mtk_pcie_direct_msi_handler(struct irq_desc *desc)
+static int mtk_pcie_parse_msi(struct mtk_pcie_port *port)
 {
-	struct mtk_pcie_port *port = irq_desc_get_handler_data(desc);
-	struct irq_chip *irqchip = irq_desc_get_chip(desc);
-	unsigned long msi_enable, msi_status;
-	unsigned int virq;
-	irq_hw_number_t hwirq;
-	int i, msi_bit = -EINVAL;
+	struct device *dev = port->dev;
+	struct device_node *node = dev->of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+	const char *msi_type;
+	u32 mask_check = 0, *msimap;
+	int count, err, i;
 
-	for (i = 0; i < PCIE_MSI_IRQS_PER_SET; i++) {
-		if (port->direct_msi[i] == irq_desc_get_irq(desc)) {
-			msi_bit = i;
-			break;
-		}
+	/* Get MSI group type */
+	port->msi_group_type = group0_merge_msi;
+	if (!of_property_read_string(node, "msi_type", &msi_type)) {
+		if (!strcmp(msi_type, "direct_msi"))
+			port->msi_group_type = group1_direct_msi;
+		if (!strcmp(msi_type, "binding_msi"))
+			port->msi_group_type = group_binding_msi;
 	}
 
-	if (msi_bit == -EINVAL)
-		return;
+	port->num_irqs = platform_irq_count(pdev);
+	port->irqs = devm_kzalloc(dev, sizeof(struct mtk_pcie_irq) * port->num_irqs,
+				  GFP_KERNEL);
+	if (!port->irqs)
+		return -ENOMEM;
 
-	chained_irq_enter(irqchip, desc);
+	/* Merge MSI don't need map table */
+	if (port->msi_group_type == group0_merge_msi) {
+		port->irqs[0].group = 0;
+		port->irqs[0].mapped_table = GENMASK(31, 0);
 
-	for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
-		struct mtk_msi_set *msi_set = &port->msi_sets[i];
+		return 0;
+	}
 
-		msi_status = readl_relaxed(msi_set->base +
-					   PCIE_MSI_SET_STATUS_OFFSET);
-		msi_enable = readl_relaxed(msi_set->base +
-					   PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-		msi_status &= msi_enable;
-		msi_status &= BIT(msi_bit);
-		if (!msi_status)
-			continue;
+	/* Parse MSI map table from dts */
+	count = of_property_count_elems_of_size(node, "msi-map", sizeof(u32));
+	if ((count <= 0) || (count / 2 > port->num_irqs))
+		return -EINVAL;
+	msimap = devm_kzalloc(dev, sizeof(u32) * count, GFP_KERNEL);
+	if (!msimap)
+		return -ENOMEM;
 
-		hwirq = msi_bit + i * PCIE_MSI_IRQS_PER_SET;
-		virq = irq_find_mapping(port->msi_bottom_domain, hwirq);
-		generic_handle_irq(virq);
+	err = of_property_read_u32_array(node, "msi-map", msimap, count);
+	if (err)
+		return err;
+
+	for (i = 0; i < (count / 2); i++) {
+		if ((msimap[i * 2] >= PCIE_MSI_GROUP_NUM) ||
+		    (msimap[i * 2 + 1] & mask_check)) {
+			return -EINVAL;
+		}
+
+		port->irqs[i].group = msimap[i * 2];
+		port->irqs[i].mapped_table = msimap[i * 2 + 1];
+		mask_check |= msimap[i * 2 + 1];
 	}
 
-	chained_irq_exit(irqchip, desc);
+	return 0;
 }
 
 static int mtk_pcie_setup_irq(struct mtk_pcie_port *port)
@@ -830,17 +944,13 @@
 	if (port->irq < 0)
 		return port->irq;
 
-	irq_set_chained_handler_and_data(port->irq, mtk_pcie_irq_handler, port);
+	for (i = 0; i < port->num_irqs; i++) {
+		port->irqs[i].irq = platform_get_irq(pdev, i);
+		if (port->irqs[i].irq < 0)
+			return port->irqs[i].irq;
 
-	if (port->direct_msi_enable) {
-		mtk_msi_bottom_irq_chip.irq_set_affinity =
-						      mtk_pcie_set_msi_affinity;
-
-		for (i = 0; i < PCIE_MSI_IRQS_PER_SET; i++) {
-			port->direct_msi[i] = platform_get_irq(pdev, i + 1);
-			irq_set_chained_handler_and_data(port->direct_msi[i],
-					    mtk_pcie_direct_msi_handler, port);
-		}
+		irq_set_chained_handler_and_data(port->irqs[i].irq,
+						 mtk_pcie_irq_handler, port);
 	}
 
 	return 0;
@@ -907,6 +1017,12 @@
 	if (port->max_link_width < 0)
 		dev_err(dev, "failed to get max link width\n");
 
+	ret = mtk_pcie_parse_msi(port);
+	if (ret) {
+		dev_err(dev, "failed to parse msi\n");
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1054,7 +1170,7 @@
 
 static void __maybe_unused mtk_pcie_irq_save(struct mtk_pcie_port *port)
 {
-	int i;
+	int i, n;
 
 	raw_spin_lock(&port->irq_lock);
 
@@ -1063,12 +1179,9 @@
 	for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
 		struct mtk_msi_set *msi_set = &port->msi_sets[i];
 
-		if (port->direct_msi_enable)
-			msi_set->saved_irq_state = readl_relaxed(msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-		else
-			msi_set->saved_irq_state = readl_relaxed(msi_set->base +
-					PCIE_MSI_SET_ENABLE_OFFSET);
+		for (n = 0; n < PCIE_MSI_GROUP_NUM; n++)
+			msi_set->saved_irq_state[n] = readl_relaxed(
+							msi_set->enable[n]);
 	}
 
 	raw_spin_unlock(&port->irq_lock);
@@ -1076,7 +1189,7 @@
 
 static void __maybe_unused mtk_pcie_irq_restore(struct mtk_pcie_port *port)
 {
-	int i;
+	int i, n;
 
 	raw_spin_lock(&port->irq_lock);
 
@@ -1085,12 +1198,9 @@
 	for (i = 0; i < PCIE_MSI_SET_NUM; i++) {
 		struct mtk_msi_set *msi_set = &port->msi_sets[i];
 
-		if (port->direct_msi_enable)
-			writel_relaxed(msi_set->saved_irq_state, msi_set->base +
-					PCIE_MSI_SET_GRP1_ENABLE_OFFSET);
-		else
-			writel_relaxed(msi_set->saved_irq_state, msi_set->base +
-					PCIE_MSI_SET_ENABLE_OFFSET);
+		for (n = 0; n < PCIE_MSI_GROUP_NUM; n++)
+			writel_relaxed(msi_set->saved_irq_state[n],
+				       msi_set->enable[n]);
 	}
 
 	raw_spin_unlock(&port->irq_lock);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
index ae4e9c1..09502e9 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
@@ -206,8 +206,8 @@
 +		mtk_wed_add_hw(np, eth, wdma, i);
 +	}
 +
- 	for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
- 		eth->irq_pdma[i] = platform_get_irq(pdev, i);
+ 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+ 		for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
  
 @@ -5170,10 +5200,11 @@ static int mtk_probe(struct platform_device *pdev)
  	}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
index ba9bc98..d41c0f3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
@@ -9,20 +9,27 @@
  		goto resume;
  
  	do {
-@@ -568,16 +568,6 @@ int xfrm_output(struct sock *sk, struct
- 	struct xfrm_state *x = skb_dst(skb)->xfrm;
- 	int err;
+@@ -570,12 +570,10 @@ int xfrm_output(struct sock *sk, struct
  
--	if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) {
--		if (!xfrm_dev_offload_ok(skb, x)) {
+ 	if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) {
+ 		if (!xfrm_dev_offload_ok(skb, x)) {
 -			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
 -			kfree_skb(skb);
 -			return -EHOSTUNREACH;
--		}
++			secpath_reset(skb);
++			goto sw_path;
+ 		}
 -
 -		return xfrm_output_resume(skb, 0);
--	}
--
- 	secpath_reset(skb);
++		return 0;
+ 	}
  
- 	if (xfrm_dev_offload_ok(skb, x)) {
+ 	secpath_reset(skb);
+@@ -606,6 +604,7 @@ int xfrm_output(struct sock *sk, struct
+ 		if (x->xso.dev && x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)
+ 			goto out;
+ 	} else {
++sw_path:
+ 		if (skb_is_gso(skb))
+ 			return xfrm_output_gso(net, sk, skb);
+ 	}
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 75880ed..96deb54 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,6 +1,33 @@
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2316,6 +2316,7 @@ static int mtk_poll_rx(struct napi_struc
+@@ -1840,6 +1840,11 @@ 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_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
++		data &= ((~TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT);
++		data |= (EIP197_QDMA_TPORT & TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT;
++	}
+ 	WRITE_ONCE(desc->txd4, data);
+ 
+ 	data = 0;
+@@ -1862,6 +1867,14 @@ static void mtk_tx_set_dma_desc_v3(struc
+ 
+ 	WRITE_ONCE(desc->txd7, 0);
+ 	WRITE_ONCE(desc->txd8, 0);
++	if (unlikely(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);
++	}
+ }
+ 
+ static void mtk_tx_set_dma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
+@@ -2331,6 +2344,7 @@ static int mtk_poll_rx(struct napi_struc
  
  		skb_hnat_alg(skb) = 0;
  		skb_hnat_filled(skb) = 0;
@@ -20,24 +47,6 @@
  	rcu_read_lock_bh();
  	nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
  	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
-@@ -1097,7 +1100,7 @@ static unsigned int hnat_ipv4_get_nextho
- 	 * outer header, we must update its outer mac header pointer
- 	 * before filling outer mac or it may screw up inner mac
- 	 */
--	if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
-+	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb)) {
- 		skb_push(skb, sizeof(struct ethhdr));
- 		skb_reset_mac_header(skb);
- 	}
-@@ -1105,7 +1108,7 @@ static unsigned int hnat_ipv4_get_nextho
- 	memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
- 	memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
- 
--	if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
-+	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb))
- 		skb_pull(skb, sizeof(struct ethhdr));
- 
- 	rcu_read_unlock_bh();
 @@ -1299,6 +1302,9 @@ static inline void hnat_fill_offload_eng
  		 */
  		entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
@@ -48,36 +57,83 @@
  	} else {
  		return;
  	}
-@@ -1344,7 +1350,8 @@ static unsigned int skb_to_hnat_info(str
- 	if (whnat && is_hnat_pre_filled(foe))
- 		return 0;
- 
--	if (skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL)) {
-+	if ((skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL))
-+	    || (skb_hnat_cdrt(skb) && skb_dst(skb) && !dst_xfrm(skb_dst(skb)))) {
- 		hnat_get_filled_unbind_entry(skb, &entry);
- 		goto hnat_entry_bind;
- 	}
-@@ -1744,7 +1751,8 @@ static unsigned int skb_to_hnat_info(str
- 	/* Fill Layer2 Info.*/
- 	entry = ppe_fill_L2_info(eth, entry, hw_path);
- 
--	if (skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
-+	if ((skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
-+	    || (!skb_hnat_cdrt(skb) && skb_dst(skb) && dst_xfrm(skb_dst(skb))))
- 		goto hnat_entry_skip_bind;
- 
- hnat_entry_bind:
-@@ -1950,6 +1958,8 @@ hnat_entry_bind:
- 
- #if defined(CONFIG_MEDIATEK_NETSYS_V3)
- 	hnat_fill_offload_engine_entry(skb, &entry, dev);
-+	if (skb_hnat_cdrt(skb))
-+		entry = ppe_fill_L2_info(eth, entry, hw_path);
- #endif
+@@ -1308,6 +1314,75 @@ static inline void hnat_fill_offload_eng
+ #endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
+ }
  
- hnat_entry_skip_bind:
-@@ -2227,6 +2237,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
++int hnat_bind_crypto_entry(struct sk_buff *skb, const struct net_device *dev) {
++	struct foe_entry *foe;
++	struct foe_entry entry = { 0 };
++	struct ethhdr *eth = eth_hdr(skb);
++	u32 gmac = NR_DISCARD;
++
++	if (skb_hnat_tops(skb) && mtk_tnl_encap_offload)
++		mtk_tnl_encap_offload(skb);
++
++	foe = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
++
++	hnat_get_filled_unbind_entry(skb, &entry);
++	entry.bfib1.cah = 1;
++	entry.bfib1.time_stamp = (hnat_priv->data->version == MTK_HNAT_V2 ||
++				 hnat_priv->data->version == MTK_HNAT_V3) ?
++		readl(hnat_priv->fe_base + 0x0010) & (0xFF) :
++		readl(hnat_priv->fe_base + 0x0010) & (0x7FFF);
++	entry.ipv4_hnapt.iblk2.port_ag =
++		(hnat_priv->data->version == MTK_HNAT_V2 ||
++		 hnat_priv->data->version == MTK_HNAT_V3) ? 0xf : 0x3f;
++
++	if (IS_LAN(dev)) {
++		if (IS_BOND_MODE)
++			gmac = ((skb_hnat_entry(skb) >> 1) % hnat_priv->gmac_num) ?
++				 NR_GMAC2_PORT : NR_GMAC1_PORT;
++		else
++			gmac = NR_GMAC1_PORT;
++	} else if (IS_LAN2(dev)) {
++		gmac = NR_GMAC2_PORT;
++	} else if (IS_WAN(dev)) {
++		gmac = (IS_GMAC1_MODE) ? NR_GMAC1_PORT : NR_GMAC2_PORT;
++	} else {
++		pr_notice("Unknown case of dp, iif=%x --> %s\n", skb_hnat_iface(skb), dev->name);
++		return -1;
++	}
++
++	entry.ipv4_hnapt.iblk2.mibf = 1;
++	entry.ipv4_hnapt.iblk2.dp = gmac;
++	entry.ipv4_hnapt.iblk2.port_mg =
++		(hnat_priv->data->version == MTK_HNAT_V1_1) ? 0x3f : 0;
++	entry.bfib1.ttl = 1;
++	entry.bfib1.state = BIND;
++
++	hnat_fill_offload_engine_entry(skb, &entry, dev);
++
++	if (!skb_hnat_tops(skb)) {
++		entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)eth->h_dest));
++		entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&eth->h_dest[4]));
++		entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source));
++		entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&eth->h_source[4]));
++	}
++
++	wmb();
++
++	if (entry_hnat_is_bound(foe))
++		return 0;
++
++	memcpy(foe, &entry, sizeof(entry));
++
++	if (hnat_priv->data->per_flow_accounting &&
++	    skb_hnat_entry(skb) < hnat_priv->foe_etry_num &&
++	    skb_hnat_ppe(skb) < CFG_PPE_NUM)
++		memset(&hnat_priv->acct[skb_hnat_ppe(skb)][skb_hnat_entry(skb)],
++		       0, sizeof(struct mib_entry));
++
++	return 0;
++}
++EXPORT_SYMBOL(hnat_bind_crypto_entry);
++
+ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
+ 				     const struct net_device *dev,
+ 				     struct foe_entry *foe,
+@@ -2364,6 +2439,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
  
  	skb_hnat_alg(skb) = 0;
  	skb_hnat_set_tops(skb, 0);
@@ -85,7 +141,7 @@
  	skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
  
  	if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -2313,7 +2324,8 @@ static unsigned int mtk_hnat_accel_type(
+@@ -2450,7 +2526,8 @@ static unsigned int mtk_hnat_accel_type(
  	 * is from local_out which is also filtered in sanity check.
  	 */
  	dst = skb_dst(skb);
@@ -95,7 +151,7 @@
  		return 0;
  
  	ct = nf_ct_get(skb, &ctinfo);
-@@ -2709,6 +2721,14 @@ static unsigned int mtk_hnat_nf_post_rou
+@@ -2847,6 +2924,14 @@ static unsigned int mtk_hnat_nf_post_rou
  		}
  	}
  
@@ -110,7 +166,7 @@
  	if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
  		is_virt_dev = true;
  
-@@ -3016,7 +3036,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+@@ -3157,7 +3242,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);
@@ -164,7 +220,7 @@
  {
 --- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
 +++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1087,6 +1087,8 @@ enum FoeIpAct {
+@@ -1135,6 +1135,8 @@ enum FoeIpAct {
  #define NR_WDMA1_PORT 9
  #define NR_WDMA2_PORT 13
  #define NR_GMAC3_PORT 15
@@ -173,11 +229,35 @@
  #define NR_TDMA_TPORT 4
  #define NR_TDMA_QDMA_TPORT 5
  #define LAN_DEV_NAME hnat_priv->lan
-@@ -1233,6 +1235,7 @@ extern int qos_toggle;
+@@ -1288,6 +1290,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);
 +extern bool (*mtk_crypto_offloadable)(struct sk_buff *skb);
++extern int hnat_bind_crypto_entry(struct sk_buff *skb, const struct net_device *dev);
  
  int ext_if_add(struct extdev_entry *ext_entry);
  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
+@@ -551,6 +551,10 @@
+ 
+ #define MTK_QDMA_GMAC2_QID	8
+ 
++/* QDMA V2 descriptor txd8 */
++#define TX_DMA_CDRT_SHIFT 	0
++#define TX_DMA_CDRT_MASK	0xff
++
+ /* QDMA V2 descriptor txd6 */
+ #define TX_DMA_INS_VLAN_V2         BIT(16)
+ 
+@@ -560,6 +564,9 @@
+ #define TX_DMA_SPTAG_V3            BIT(27)
+ 
+ /* QDMA V2 descriptor txd4 */
++#define EIP197_QDMA_TPORT          3
++#define TX_DMA_TPORT_SHIFT         0
++#define TX_DMA_TPORT_MASK          0xf
+ #define TX_DMA_FPORT_SHIFT_V2      8
+ #define TX_DMA_FPORT_MASK_V2       0xf
+ #define TX_DMA_SWC_V2              BIT(30)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
index b2cc240..608bc91 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
 +++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1091,6 +1091,8 @@ enum FoeIpAct {
+@@ -1139,6 +1139,8 @@ enum FoeIpAct {
  #define NR_EIP197_QDMA_TPORT 3
  #define NR_TDMA_TPORT 4
  #define NR_TDMA_QDMA_TPORT 5
@@ -11,27 +11,27 @@
  #define IS_WAN(dev)                                                            \
 --- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
 +++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-@@ -1099,7 +1099,8 @@ static unsigned int hnat_ipv4_get_nextho
+@@ -1101,7 +1101,8 @@ static unsigned int hnat_ipv4_get_nextho
  	 * outer header, we must update its outer mac header pointer
  	 * before filling outer mac or it may screw up inner mac
  	 */
--	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb)) {
+-	if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
 +	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
 +	    || (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb))) {
  		skb_push(skb, sizeof(struct ethhdr));
  		skb_reset_mac_header(skb);
  	}
-@@ -1107,7 +1108,8 @@ static unsigned int hnat_ipv4_get_nextho
+@@ -1109,7 +1110,8 @@ static unsigned int hnat_ipv4_get_nextho
  	memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
  	memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
  
--	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) || skb_hnat_cdrt(skb))
+-	if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
 +	if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
 +	    || (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)))
  		skb_pull(skb, sizeof(struct ethhdr));
  
  	rcu_read_unlock_bh();
-@@ -1255,6 +1257,38 @@ static inline void hnat_get_filled_unbin
+@@ -1257,6 +1259,38 @@ static inline void hnat_get_filled_unbin
  	entry->bfib1.ps = 0;
  }
  
@@ -70,7 +70,7 @@
  static inline void hnat_qos_tnl(u32 id, const struct net_device *dev)
  {
  	u32 cfg;
-@@ -1299,9 +1333,15 @@ static inline void hnat_fill_offload_eng
+@@ -1301,9 +1335,15 @@ static inline void hnat_fill_offload_eng
  		 * we fill in hnat tport and tops_entry for tunnel encapsulation
  		 * offloading
  		 */
@@ -88,20 +88,19 @@
  		entry->ipv4_hnapt.tport_id = NR_EIP197_QDMA_TPORT;
  		entry->ipv4_hnapt.cdrt_id = skb_hnat_cdrt(skb);
  	} else {
-@@ -1333,6 +1373,7 @@ static unsigned int skb_to_hnat_info(str
+@@ -1404,6 +1444,7 @@ static unsigned int skb_to_hnat_info(str
  	u32 port_id = 0;
  	u32 payload_len = 0;
  	int mape = 0;
 +	int ret;
+ 	struct mtk_mac *mac = netdev_priv(dev);
  
  	ct = nf_ct_get(skb, &ctinfo);
- 
-@@ -1349,10 +1390,12 @@ static unsigned int skb_to_hnat_info(str
+@@ -1421,9 +1462,12 @@ static unsigned int skb_to_hnat_info(str
  	if (whnat && is_hnat_pre_filled(foe))
  		return 0;
  
--	if ((skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL))
--	    || (skb_hnat_cdrt(skb) && skb_dst(skb) && !dst_xfrm(skb_dst(skb)))) {
+-	if (skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL)) {
 +	ret = hnat_offload_engine_done(skb, hw_path);
 +	if (ret == 1) {
  		hnat_get_filled_unbind_entry(skb, &entry);
@@ -111,26 +110,18 @@
  	}
  
  	entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
-@@ -1751,7 +1794,8 @@ static unsigned int skb_to_hnat_info(str
+@@ -1869,7 +1913,9 @@ static unsigned int skb_to_hnat_info(str
+ 	/* Fill Layer2 Info.*/
  	entry = ppe_fill_L2_info(eth, entry, hw_path);
  
- 	if ((skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
--	    || (!skb_hnat_cdrt(skb) && skb_dst(skb) && dst_xfrm(skb_dst(skb))))
+-	if (skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
++	if ((skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
 +	    || (!skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb)
-+	        && skb_dst(skb) && dst_xfrm(skb_dst(skb))))
++		&& skb_dst(skb) && dst_xfrm(skb_dst(skb))))
  		goto hnat_entry_skip_bind;
  
  hnat_entry_bind:
-@@ -1957,7 +2001,7 @@ hnat_entry_bind:
- 
- #if defined(CONFIG_MEDIATEK_NETSYS_V3)
- 	hnat_fill_offload_engine_entry(skb, &entry, dev);
--	if (skb_hnat_cdrt(skb))
-+	if (skb_hnat_cdrt(skb) && skb_hnat_is_encrypt(skb))
- 		entry = ppe_fill_L2_info(eth, entry, hw_path);
- #endif
- 
-@@ -2237,6 +2281,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+@@ -2445,6 +2491,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
  	skb_hnat_alg(skb) = 0;
  	skb_hnat_set_tops(skb, 0);
  	skb_hnat_set_cdrt(skb, 0);
@@ -138,7 +129,7 @@
  	skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
  
  	if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -3037,7 +3082,8 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+@@ -3248,7 +3295,8 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
  		entry->udib1.pkt_type = IPV6_6RD;
  		hnat_set_head_frags(state, skb, 0, hnat_set_alg);
  	} else if (is_magic_tag_valid(skb)
@@ -150,7 +141,7 @@
  		hnat_set_head_frags(state, skb, 1, hnat_set_alg);
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2324,10 +2324,11 @@ static int mtk_poll_rx(struct napi_struc
+@@ -2306,10 +2306,11 @@ static int mtk_poll_rx(struct napi_struc
  
  		skb_hnat_alg(skb) = 0;
  		skb_hnat_filled(skb) = 0;
@@ -165,7 +156,7 @@
  			trace_printk("[%s] reason=0x%x(force to CPU) from WAN to Ext\n",
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -640,6 +640,9 @@
+@@ -652,6 +652,9 @@
  #define RX_DMA_GET_AGG_CNT_V2(_x)	(((_x) >> 16) & 0xff)
  #define RX_DMA_GET_TOPS_CRSN(_x)	(((_x) >> 24) & 0xff)