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

[Description]
a12f13c9 [MAC80211][wed][fix fw download fail issue when wed on/off]
a6f5795f [kernel][common][add dhrystone default setting to kernel config]
3aff7191 [kernel][mt7988][backport dhrystone from kernel 6.4]
2f4d3117 [Kernel][hnat][Fix Veth TX packets issue]
609729f6 [kernel][common][hnat][Refine HNAT prefilled flow for the WiFi Tx]

[Release-log]

Change-Id: I1d142b96a7cff2e80767aa6556f058a86ffc2907
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch
new file mode 100644
index 0000000..a299b20
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch
@@ -0,0 +1,1036 @@
+From d5528cc16893f1f64b07936b1e88aa023128debb Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+Date: Thu, 8 Dec 2022 15:31:28 +0100
+Subject: [PATCH] lib: add Dhrystone benchmark test
+
+When working on SoC bring-up, (a full) userspace may not be available,
+making it hard to benchmark the CPU performance of the system under
+development.  Still, one may want to have a rough idea of the (relative)
+performance of one or more CPU cores, especially when working on e.g.  the
+clock driver that controls the CPU core clock(s).
+
+Hence make the classical Dhrystone 2.1 benchmark available as a Linux
+kernel test module, based on[1].
+
+When built-in, this benchmark can be run without any userspace present.
+
+Parallel runs (run on multiple CPU cores) are supported, just kick the
+"run" file multiple times.
+
+Note that the actual figures depend on the configuration options that
+control compiler optimization (e.g.  CONFIG_CC_OPTIMIZE_FOR_SIZE vs.
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE), and on the compiler options used when
+building the kernel in general.  Hence numbers may differ from those
+obtained by running similar benchmarks in userspace.
+
+[1] https://github.com/qris/dhrystone-deb.git
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lkml.kernel.org/r/4d07ad990740a5f1e426ce4566fb514f60ec9bdd.1670509558.git.geert+renesas@glider.be
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Brendan Higgins <brendanhiggins@google.com>
+Cc: David Gow <davidgow@google.com>
+[geert+renesas@glider.be: fix uninitialized use of ret]
+ Link: https://lkml.kernel.org/r/alpine.DEB.2.22.394.2212190857310.137329@ramsan.of.borg
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+---
+ lib/Kconfig.debug |  35 +++++
+ lib/Makefile      |   2 +
+ lib/dhry.h        | 358 ++++++++++++++++++++++++++++++++++++++++++++++
+ lib/dhry_1.c      | 283 ++++++++++++++++++++++++++++++++++++
+ lib/dhry_2.c      | 175 ++++++++++++++++++++++
+ lib/dhry_run.c    |  85 +++++++++++
+ 6 files changed, 938 insertions(+)
+ create mode 100644 lib/dhry.h
+ create mode 100644 lib/dhry_1.c
+ create mode 100644 lib/dhry_2.c
+ create mode 100644 lib/dhry_run.c
+
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 881c3f84e88a..918bda4ee120 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -2079,6 +2079,41 @@ menuconfig RUNTIME_TESTING_MENU
+ 
+ if RUNTIME_TESTING_MENU
+ 
++config TEST_DHRY
++	tristate "Dhrystone benchmark test"
++	help
++	  Enable this to include the Dhrystone 2.1 benchmark.  This test
++	  calculates the number of Dhrystones per second, and the number of
++	  DMIPS (Dhrystone MIPS) obtained when the Dhrystone score is divided
++	  by 1757 (the number of Dhrystones per second obtained on the VAX
++	  11/780, nominally a 1 MIPS machine).
++
++	  To run the benchmark, it needs to be enabled explicitly, either from
++	  the kernel command line (when built-in), or from userspace (when
++	  built-in or modular.
++
++	  Run once during kernel boot:
++
++	      test_dhry.run
++
++	  Set number of iterations from kernel command line:
++
++	      test_dhry.iterations=<n>
++
++	  Set number of iterations from userspace:
++
++	      echo <n> > /sys/module/test_dhry/parameters/iterations
++
++	  Trigger manual run from userspace:
++
++	      echo y > /sys/module/test_dhry/parameters/run
++
++	  If the number of iterations is <= 0, the test will devise a suitable
++	  number of iterations (test runs for at least 2s) automatically.
++	  This process takes ca. 4s.
++
++	  If unsure, say N.
++
+ config LKDTM
+ 	tristate "Linux Kernel Dump Test Tool Module"
+ 	depends on DEBUG_FS
+diff --git a/lib/Makefile b/lib/Makefile
+index 4d9461bfea42..06b9dcd80cda 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -57,6 +57,8 @@ obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
+ obj-y += kstrtox.o
+ obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
+ obj-$(CONFIG_TEST_BPF) += test_bpf.o
++test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o
++obj-$(CONFIG_TEST_DHRY) += test_dhry.o
+ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+ obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
+ CFLAGS_test_bitops.o += -Werror
+diff --git a/lib/dhry.h b/lib/dhry.h
+new file mode 100644
+index 000000000000..e1a4db8e252c
+--- /dev/null
++++ b/lib/dhry.h
+@@ -0,0 +1,358 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry.h (part 1 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *                      Siemens AG, AUT E 51
++ *                      Postfach 3220
++ *                      8520 Erlangen
++ *                      Germany (West)
++ *                              Phone:  [+49]-9131-7-20330
++ *                                      (8-17 Central European Time)
++ *                              Usenet: ..!mcsun!unido!estevax!weicker
++ *
++ *              Original Version (in Ada) published in
++ *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
++ *              pp. 1013 - 1030, together with the statistics
++ *              on which the distribution of statements etc. is based.
++ *
++ *              In this C version, the following C library functions are used:
++ *              - strcpy, strcmp (inside the measurement loop)
++ *              - printf, scanf (outside the measurement loop)
++ *              In addition, Berkeley UNIX system calls "times ()" or "time ()"
++ *              are used for execution time measurement. For measurements
++ *              on other systems, these calls have to be changed.
++ *
++ *  Collection of Results:
++ *              Reinhold Weicker (address see above) and
++ *
++ *              Rick Richardson
++ *              PC Research. Inc.
++ *              94 Apple Orchard Drive
++ *              Tinton Falls, NJ 07724
++ *                      Phone:  (201) 389-8963 (9-17 EST)
++ *                      Usenet: ...!uunet!pcrat!rick
++ *
++ *      Please send results to Rick Richardson and/or Reinhold Weicker.
++ *      Complete information should be given on hardware and software used.
++ *      Hardware information includes: Machine type, CPU, type and size
++ *      of caches; for microprocessors: clock frequency, memory speed
++ *      (number of wait states).
++ *      Software information includes: Compiler (and runtime library)
++ *      manufacturer and version, compilation switches, OS version.
++ *      The Operating System version may give an indication about the
++ *      compiler; Dhrystone itself performs no OS calls in the measurement loop.
++ *
++ *      The complete output generated by the program should be mailed
++ *      such that at least some checks for correctness can be made.
++ *
++ ***************************************************************************
++ *
++ *  History:    This version C/2.1 has been made for two reasons:
++ *
++ *              1) There is an obvious need for a common C version of
++ *              Dhrystone, since C is at present the most popular system
++ *              programming language for the class of processors
++ *              (microcomputers, minicomputers) where Dhrystone is used most.
++ *              There should be, as far as possible, only one C version of
++ *              Dhrystone such that results can be compared without
++ *              restrictions. In the past, the C versions distributed
++ *              by Rick Richardson (Version 1.1) and by Reinhold Weicker
++ *              had small (though not significant) differences.
++ *
++ *              2) As far as it is possible without changes to the Dhrystone
++ *              statistics, optimizing compilers should be prevented from
++ *              removing significant statements.
++ *
++ *              This C version has been developed in cooperation with
++ *              Rick Richardson (Tinton Falls, NJ), it incorporates many
++ *              ideas from the "Version 1.1" distributed previously by
++ *              him over the UNIX network Usenet.
++ *              I also thank Chaim Benedelac (National Semiconductor),
++ *              David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
++ *              Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
++ *              for their help with comments on earlier versions of the
++ *              benchmark.
++ *
++ *  Changes:    In the initialization part, this version follows mostly
++ *              Rick Richardson's version distributed via Usenet, not the
++ *              version distributed earlier via floppy disk by Reinhold Weicker.
++ *              As a concession to older compilers, names have been made
++ *              unique within the first 8 characters.
++ *              Inside the measurement loop, this version follows the
++ *              version previously distributed by Reinhold Weicker.
++ *
++ *              At several places in the benchmark, code has been added,
++ *              but within the measurement loop only in branches that
++ *              are not executed. The intention is that optimizing compilers
++ *              should be prevented from moving code out of the measurement
++ *              loop, or from removing code altogether. Since the statements
++ *              that are executed within the measurement loop have NOT been
++ *              changed, the numbers defining the "Dhrystone distribution"
++ *              (distribution of statements, operand types and locality)
++ *              still hold. Except for sophisticated optimizing compilers,
++ *              execution times for this version should be the same as
++ *              for previous versions.
++ *
++ *              Since it has proven difficult to subtract the time for the
++ *              measurement loop overhead in a correct way, the loop check
++ *              has been made a part of the benchmark. This does have
++ *              an impact - though a very minor one - on the distribution
++ *              statistics which have been updated for this version.
++ *
++ *              All changes within the measurement loop are described
++ *              and discussed in the companion paper "Rationale for
++ *              Dhrystone version 2".
++ *
++ *              Because of the self-imposed limitation that the order and
++ *              distribution of the executed statements should not be
++ *              changed, there are still cases where optimizing compilers
++ *              may not generate code for some statements. To a certain
++ *              degree, this is unavoidable for small synthetic benchmarks.
++ *              Users of the benchmark are advised to check code listings
++ *              whether code is generated for all statements of Dhrystone.
++ *
++ *              Version 2.1 is identical to version 2.0 distributed via
++ *              the UNIX network Usenet in March 1988 except that it corrects
++ *              some minor deficiencies that were found by users of version 2.0.
++ *              The only change within the measurement loop is that a
++ *              non-executed "else" part was added to the "if" statement in
++ *              Func_3, and a non-executed "else" part removed from Proc_3.
++ *
++ ***************************************************************************
++ *
++ *  Compilation model and measurement (IMPORTANT):
++ *
++ *  This C version of Dhrystone consists of three files:
++ *  - dhry.h (this file, containing global definitions and comments)
++ *  - dhry_1.c (containing the code corresponding to Ada package Pack_1)
++ *  - dhry_2.c (containing the code corresponding to Ada package Pack_2)
++ *
++ *  The following "ground rules" apply for measurements:
++ *  - Separate compilation
++ *  - No procedure merging
++ *  - Otherwise, compiler optimizations are allowed but should be indicated
++ *  - Default results are those without register declarations
++ *  See the companion paper "Rationale for Dhrystone Version 2" for a more
++ *  detailed discussion of these ground rules.
++ *
++ *  For 16-Bit processors (e.g. 80186, 80286), times for all compilation
++ *  models ("small", "medium", "large" etc.) should be given if possible,
++ *  together with a definition of these models for the compiler system used.
++ *
++ **************************************************************************
++ *
++ *  Dhrystone (C version) statistics:
++ *
++ *  [Comment from the first distribution, updated for version 2.
++ *   Note that because of language differences, the numbers are slightly
++ *   different from the Ada version.]
++ *
++ *  The following program contains statements of a high level programming
++ *  language (here: C) in a distribution considered representative:
++ *
++ *    assignments                  52 (51.0 %)
++ *    control statements           33 (32.4 %)
++ *    procedure, function calls    17 (16.7 %)
++ *
++ *  103 statements are dynamically executed. The program is balanced with
++ *  respect to the three aspects:
++ *
++ *    - statement type
++ *    - operand type
++ *    - operand locality
++ *         operand global, local, parameter, or constant.
++ *
++ *  The combination of these three aspects is balanced only approximately.
++ *
++ *  1. Statement Type:
++ *  -----------------             number
++ *
++ *     V1 = V2                     9
++ *       (incl. V1 = F(..)
++ *     V = Constant               12
++ *     Assignment,                 7
++ *       with array element
++ *     Assignment,                 6
++ *       with record component
++ *                                --
++ *                                34       34
++ *
++ *     X = Y +|-|"&&"|"|" Z        5
++ *     X = Y +|-|"==" Constant     6
++ *     X = X +|- 1                 3
++ *     X = Y *|/ Z                 2
++ *     X = Expression,             1
++ *           two operators
++ *     X = Expression,             1
++ *           three operators
++ *                                --
++ *                                18       18
++ *
++ *     if ....                    14
++ *       with "else"      7
++ *       without "else"   7
++ *           executed        3
++ *           not executed    4
++ *     for ...                     7  |  counted every time
++ *     while ...                   4  |  the loop condition
++ *     do ... while                1  |  is evaluated
++ *     switch ...                  1
++ *     break                       1
++ *     declaration with            1
++ *       initialization
++ *                                --
++ *                                34       34
++ *
++ *     P (...)  procedure call    11
++ *       user procedure      10
++ *       library procedure    1
++ *     X = F (...)
++ *             function  call      6
++ *       user function        5
++ *       library function     1
++ *                                --
++ *                                17       17
++ *                                        ---
++ *                                        103
++ *
++ *    The average number of parameters in procedure or function calls
++ *    is 1.82 (not counting the function values as implicit parameters).
++ *
++ *
++ *  2. Operators
++ *  ------------
++ *                          number    approximate
++ *                                    percentage
++ *
++ *    Arithmetic             32          50.8
++ *
++ *       +                     21          33.3
++ *       -                      7          11.1
++ *       *                      3           4.8
++ *       / (int div)            1           1.6
++ *
++ *    Comparison             27           42.8
++ *
++ *       ==                     9           14.3
++ *       /=                     4            6.3
++ *       >                      1            1.6
++ *       <                      3            4.8
++ *       >=                     1            1.6
++ *       <=                     9           14.3
++ *
++ *    Logic                   4            6.3
++ *
++ *       && (AND-THEN)          1            1.6
++ *       |  (OR)                1            1.6
++ *       !  (NOT)               2            3.2
++ *
++ *                           --          -----
++ *                           63          100.1
++ *
++ *
++ *  3. Operand Type (counted once per operand reference):
++ *  ---------------
++ *                          number    approximate
++ *                                    percentage
++ *
++ *     Integer               175        72.3 %
++ *     Character              45        18.6 %
++ *     Pointer                12         5.0 %
++ *     String30                6         2.5 %
++ *     Array                   2         0.8 %
++ *     Record                  2         0.8 %
++ *                           ---       -------
++ *                           242       100.0 %
++ *
++ *  When there is an access path leading to the final operand (e.g. a record
++ *  component), only the final data type on the access path is counted.
++ *
++ *
++ *  4. Operand Locality:
++ *  -------------------
++ *                                number    approximate
++ *                                          percentage
++ *
++ *     local variable              114        47.1 %
++ *     global variable              22         9.1 %
++ *     parameter                    45        18.6 %
++ *        value                        23         9.5 %
++ *        reference                    22         9.1 %
++ *     function result               6         2.5 %
++ *     constant                     55        22.7 %
++ *                                 ---       -------
++ *                                 242       100.0 %
++ *
++ *
++ *  The program does not compute anything meaningful, but it is syntactically
++ *  and semantically correct. All variables have a value assigned to them
++ *  before they are used as a source operand.
++ *
++ *  There has been no explicit effort to account for the effects of a
++ *  cache, or to balance the use of long or short displacements for code or
++ *  data.
++ *
++ ***************************************************************************
++ */
++
++typedef enum {
++	Ident_1,
++	Ident_2,
++	Ident_3,
++	Ident_4,
++	Ident_5
++} Enumeration;	/* for boolean and enumeration types in Ada, Pascal */
++
++/* General definitions: */
++
++typedef int One_Thirty;
++typedef int One_Fifty;
++typedef char Capital_Letter;
++typedef int Boolean;
++typedef char Str_30[31];
++typedef int Arr_1_Dim[50];
++typedef int Arr_2_Dim[50][50];
++
++typedef struct record {
++	struct record *Ptr_Comp;
++	Enumeration    Discr;
++	union {
++		struct {
++			Enumeration Enum_Comp;
++			int Int_Comp;
++			char Str_Comp[31];
++		} var_1;
++		struct {
++			Enumeration E_Comp_2;
++			char Str_2_Comp[31];
++		} var_2;
++		struct {
++			char Ch_1_Comp;
++			char Ch_2_Comp;
++		} var_3;
++	} variant;
++} Rec_Type, *Rec_Pointer;
++
++
++extern int Int_Glob;
++extern char Ch_1_Glob;
++
++void Proc_6(Enumeration  Enum_Val_Par, Enumeration *Enum_Ref_Par);
++void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val,
++	    One_Fifty *Int_Par_Ref);
++void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref,
++	    int Int_1_Par_Val, int Int_2_Par_Val);
++Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
++Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
++
++int dhry(int n);
+diff --git a/lib/dhry_1.c b/lib/dhry_1.c
+new file mode 100644
+index 000000000000..83247106824c
+--- /dev/null
++++ b/lib/dhry_1.c
+@@ -0,0 +1,283 @@
++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry_1.c (part 2 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *
++ ****************************************************************************
++ */
++
++#include "dhry.h"
++
++#include <linux/ktime.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++
++/* Global Variables: */
++
++int Int_Glob;
++char Ch_1_Glob;
++
++static Rec_Pointer Ptr_Glob, Next_Ptr_Glob;
++static Boolean Bool_Glob;
++static char Ch_2_Glob;
++static int Arr_1_Glob[50];
++static int Arr_2_Glob[50][50];
++
++static void Proc_3(Rec_Pointer *Ptr_Ref_Par)
++/******************/
++/* executed once */
++/* Ptr_Ref_Par becomes Ptr_Glob */
++{
++	if (Ptr_Glob) {
++		/* then, executed */
++		*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
++	}
++	Proc_7(10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
++} /* Proc_3 */
++
++
++static void Proc_1(Rec_Pointer Ptr_Val_Par)
++/******************/
++/* executed once */
++{
++	Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
++						/* == Ptr_Glob_Next */
++	/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
++	/* corresponds to "rename" in Ada, "with" in Pascal           */
++
++	*Ptr_Val_Par->Ptr_Comp = *Ptr_Glob;
++	Ptr_Val_Par->variant.var_1.Int_Comp = 5;
++	Next_Record->variant.var_1.Int_Comp =
++		Ptr_Val_Par->variant.var_1.Int_Comp;
++	Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
++	Proc_3(&Next_Record->Ptr_Comp);
++	/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */
++	if (Next_Record->Discr == Ident_1) {
++		/* then, executed */
++		Next_Record->variant.var_1.Int_Comp = 6;
++		Proc_6(Ptr_Val_Par->variant.var_1.Enum_Comp,
++		       &Next_Record->variant.var_1.Enum_Comp);
++		Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
++		Proc_7(Next_Record->variant.var_1.Int_Comp, 10,
++		       &Next_Record->variant.var_1.Int_Comp);
++	} else {
++		/* not executed */
++		*Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp;
++	}
++} /* Proc_1 */
++
++
++static void Proc_2(One_Fifty *Int_Par_Ref)
++/******************/
++/* executed once */
++/* *Int_Par_Ref == 1, becomes 4 */
++{
++	One_Fifty  Int_Loc;
++	Enumeration   Enum_Loc;
++
++	Int_Loc = *Int_Par_Ref + 10;
++	do {
++		/* executed once */
++		if (Ch_1_Glob == 'A') {
++			/* then, executed */
++			Int_Loc -= 1;
++			*Int_Par_Ref = Int_Loc - Int_Glob;
++			Enum_Loc = Ident_1;
++		} /* if */
++	} while (Enum_Loc != Ident_1); /* true */
++} /* Proc_2 */
++
++
++static void Proc_4(void)
++/*******/
++/* executed once */
++{
++	Boolean Bool_Loc;
++
++	Bool_Loc = Ch_1_Glob == 'A';
++	Bool_Glob = Bool_Loc | Bool_Glob;
++	Ch_2_Glob = 'B';
++} /* Proc_4 */
++
++
++static void Proc_5(void)
++/*******/
++/* executed once */
++{
++	Ch_1_Glob = 'A';
++	Bool_Glob = false;
++} /* Proc_5 */
++
++
++int dhry(int n)
++/*****/
++
++  /* main program, corresponds to procedures        */
++  /* Main and Proc_0 in the Ada version             */
++{
++	One_Fifty Int_1_Loc;
++	One_Fifty Int_2_Loc;
++	One_Fifty Int_3_Loc;
++	char Ch_Index;
++	Enumeration Enum_Loc;
++	Str_30 Str_1_Loc;
++	Str_30 Str_2_Loc;
++	int Run_Index;
++	int Number_Of_Runs;
++	ktime_t Begin_Time, End_Time;
++	u32 User_Time;
++
++	/* Initializations */
++
++	Next_Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
++	Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
++
++	Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
++	Ptr_Glob->Discr = Ident_1;
++	Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
++	Ptr_Glob->variant.var_1.Int_Comp = 40;
++	strcpy(Ptr_Glob->variant.var_1.Str_Comp,
++	       "DHRYSTONE PROGRAM, SOME STRING");
++	strcpy(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
++
++	Arr_2_Glob[8][7] = 10;
++	/* Was missing in published program. Without this statement,    */
++	/* Arr_2_Glob[8][7] would have an undefined value.             */
++	/* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
++	/* overflow may occur for this array element.                   */
++
++	pr_debug("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
++
++	Number_Of_Runs = n;
++
++	pr_debug("Execution starts, %d runs through Dhrystone\n",
++		 Number_Of_Runs);
++
++	/***************/
++	/* Start timer */
++	/***************/
++
++	Begin_Time = ktime_get();
++
++	for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
++		Proc_5();
++		Proc_4();
++		/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
++		Int_1_Loc = 2;
++		Int_2_Loc = 3;
++		strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
++		Enum_Loc = Ident_2;
++		Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
++		/* Bool_Glob == 1 */
++		while (Int_1_Loc < Int_2_Loc) {
++			/* loop body executed once */
++			Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
++			/* Int_3_Loc == 7 */
++			Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc);
++			/* Int_3_Loc == 7 */
++			Int_1_Loc += 1;
++		} /* while */
++		/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
++		Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
++		/* Int_Glob == 5 */
++		Proc_1(Ptr_Glob);
++		for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
++			/* loop body executed twice */
++			if (Enum_Loc == Func_1(Ch_Index, 'C')) {
++				/* then, not executed */
++				Proc_6(Ident_1, &Enum_Loc);
++				strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
++				Int_2_Loc = Run_Index;
++				Int_Glob = Run_Index;
++			}
++		}
++		/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
++		Int_2_Loc = Int_2_Loc * Int_1_Loc;
++		Int_1_Loc = Int_2_Loc / Int_3_Loc;
++		Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
++		/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
++		Proc_2(&Int_1_Loc);
++		/* Int_1_Loc == 5 */
++
++	} /* loop "for Run_Index" */
++
++	/**************/
++	/* Stop timer */
++	/**************/
++
++	End_Time = ktime_get();
++
++#define dhry_assert_int_eq(val, expected)				\
++	if (val != expected)						\
++		pr_err("%s: %d (FAIL, expected %d)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %d (OK)\n", #val, val)
++
++#define dhry_assert_char_eq(val, expected)				\
++	if (val != expected)						\
++		pr_err("%s: %c (FAIL, expected %c)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %c (OK)\n", #val, val)
++
++#define dhry_assert_string_eq(val, expected)				\
++	if (strcmp(val, expected))					\
++		pr_err("%s: %s (FAIL, expected %s)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %s (OK)\n", #val, val)
++
++	pr_debug("Execution ends\n");
++	pr_debug("Final values of the variables used in the benchmark:\n");
++	dhry_assert_int_eq(Int_Glob, 5);
++	dhry_assert_int_eq(Bool_Glob, 1);
++	dhry_assert_char_eq(Ch_1_Glob, 'A');
++	dhry_assert_char_eq(Ch_2_Glob, 'B');
++	dhry_assert_int_eq(Arr_1_Glob[8], 7);
++	dhry_assert_int_eq(Arr_2_Glob[8][7], Number_Of_Runs + 10);
++	pr_debug("Ptr_Comp: %px\n", Ptr_Glob->Ptr_Comp);
++	dhry_assert_int_eq(Ptr_Glob->Discr, 0);
++	dhry_assert_int_eq(Ptr_Glob->variant.var_1.Enum_Comp, 2);
++	dhry_assert_int_eq(Ptr_Glob->variant.var_1.Int_Comp, 17);
++	dhry_assert_string_eq(Ptr_Glob->variant.var_1.Str_Comp,
++			      "DHRYSTONE PROGRAM, SOME STRING");
++	if (Next_Ptr_Glob->Ptr_Comp != Ptr_Glob->Ptr_Comp)
++		pr_err("Next_Ptr_Glob->Ptr_Comp: %px (expected %px)\n",
++		       Next_Ptr_Glob->Ptr_Comp, Ptr_Glob->Ptr_Comp);
++	else
++		pr_debug("Next_Ptr_Glob->Ptr_Comp: %px\n",
++			 Next_Ptr_Glob->Ptr_Comp);
++	dhry_assert_int_eq(Next_Ptr_Glob->Discr, 0);
++	dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Enum_Comp, 1);
++	dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Int_Comp, 18);
++	dhry_assert_string_eq(Next_Ptr_Glob->variant.var_1.Str_Comp,
++			      "DHRYSTONE PROGRAM, SOME STRING");
++	dhry_assert_int_eq(Int_1_Loc, 5);
++	dhry_assert_int_eq(Int_2_Loc, 13);
++	dhry_assert_int_eq(Int_3_Loc, 7);
++	dhry_assert_int_eq(Enum_Loc, 1);
++	dhry_assert_string_eq(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
++	dhry_assert_string_eq(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
++
++	User_Time = ktime_to_ms(ktime_sub(End_Time, Begin_Time));
++
++	kfree(Ptr_Glob);
++	kfree(Next_Ptr_Glob);
++
++	/* Measurements should last at least 2 seconds */
++	if (User_Time < 2 * MSEC_PER_SEC)
++		return -EAGAIN;
++
++	return div_u64(mul_u32_u32(MSEC_PER_SEC, Number_Of_Runs), User_Time);
++}
+diff --git a/lib/dhry_2.c b/lib/dhry_2.c
+new file mode 100644
+index 000000000000..c19e661f37d3
+--- /dev/null
++++ b/lib/dhry_2.c
+@@ -0,0 +1,175 @@
++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry_2.c (part 3 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *
++ ****************************************************************************
++ */
++
++#include "dhry.h"
++
++#include <linux/string.h>
++
++
++static Boolean Func_3(Enumeration Enum_Par_Val)
++/***************************/
++/* executed once        */
++/* Enum_Par_Val == Ident_3 */
++{
++	Enumeration Enum_Loc;
++
++	Enum_Loc = Enum_Par_Val;
++	if (Enum_Loc == Ident_3) {
++		/* then, executed */
++		return true;
++	} else {
++		/* not executed */
++		return false;
++	}
++} /* Func_3 */
++
++
++void Proc_6(Enumeration  Enum_Val_Par, Enumeration *Enum_Ref_Par)
++/*********************************/
++/* executed once */
++/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
++{
++	*Enum_Ref_Par = Enum_Val_Par;
++	if (!Func_3(Enum_Val_Par)) {
++		/* then, not executed */
++		*Enum_Ref_Par = Ident_4;
++	}
++	switch (Enum_Val_Par) {
++	case Ident_1:
++		*Enum_Ref_Par = Ident_1;
++		break;
++	case Ident_2:
++		if (Int_Glob > 100) {
++			/* then */
++			*Enum_Ref_Par = Ident_1;
++		} else {
++			*Enum_Ref_Par = Ident_4;
++		}
++		break;
++	case Ident_3: /* executed */
++		*Enum_Ref_Par = Ident_2;
++		break;
++	case Ident_4:
++		break;
++	case Ident_5:
++		*Enum_Ref_Par = Ident_3;
++		break;
++	} /* switch */
++} /* Proc_6 */
++
++
++void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
++/**********************************************/
++/* executed three times                                      */
++/* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
++/*                  Int_Par_Ref becomes 7                    */
++/* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
++/*                  Int_Par_Ref becomes 17                   */
++/* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
++/*                  Int_Par_Ref becomes 18                   */
++{
++	One_Fifty Int_Loc;
++
++	Int_Loc = Int_1_Par_Val + 2;
++	*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
++} /* Proc_7 */
++
++
++void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
++/*********************************************************************/
++/* executed once      */
++/* Int_Par_Val_1 == 3 */
++/* Int_Par_Val_2 == 7 */
++{
++	One_Fifty Int_Index;
++	One_Fifty Int_Loc;
++
++	Int_Loc = Int_1_Par_Val + 5;
++	Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
++	Arr_1_Par_Ref[Int_Loc+1] = Arr_1_Par_Ref[Int_Loc];
++	Arr_1_Par_Ref[Int_Loc+30] = Int_Loc;
++	for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
++		Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
++	Arr_2_Par_Ref[Int_Loc][Int_Loc-1] += 1;
++	Arr_2_Par_Ref[Int_Loc+20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
++	Int_Glob = 5;
++} /* Proc_8 */
++
++
++Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
++/*************************************************/
++/* executed three times                                         */
++/* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
++/* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
++/* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
++{
++	Capital_Letter Ch_1_Loc;
++	Capital_Letter Ch_2_Loc;
++
++	Ch_1_Loc = Ch_1_Par_Val;
++	Ch_2_Loc = Ch_1_Loc;
++	if (Ch_2_Loc != Ch_2_Par_Val) {
++		/* then, executed */
++		return Ident_1;
++	} else {
++		/* not executed */
++		Ch_1_Glob = Ch_1_Loc;
++		return Ident_2;
++	}
++} /* Func_1 */
++
++
++Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
++/*************************************************/
++/* executed once */
++/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
++/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
++{
++	One_Thirty Int_Loc;
++	Capital_Letter Ch_Loc;
++
++	Int_Loc = 2;
++	while (Int_Loc <= 2) {
++		/* loop body executed once */
++		if (Func_1(Str_1_Par_Ref[Int_Loc],
++			   Str_2_Par_Ref[Int_Loc+1]) == Ident_1) {
++			/* then, executed */
++			Ch_Loc = 'A';
++			Int_Loc += 1;
++		}
++	} /* if, while */
++	if (Ch_Loc >= 'W' && Ch_Loc < 'Z') {
++		/* then, not executed */
++		Int_Loc = 7;
++	}
++	if (Ch_Loc == 'R') {
++		/* then, not executed */
++		return true;
++	} else {
++		/* executed */
++		if (strcmp(Str_1_Par_Ref, Str_2_Par_Ref) > 0) {
++			/* then, not executed */
++			Int_Loc += 7;
++			Int_Glob = Int_Loc;
++			return true;
++		} else {
++			/* executed */
++			return false;
++		}
++	} /* if Ch_Loc */
++} /* Func_2 */
+diff --git a/lib/dhry_run.c b/lib/dhry_run.c
+new file mode 100644
+index 000000000000..f9d33efa6d09
+--- /dev/null
++++ b/lib/dhry_run.c
+@@ -0,0 +1,85 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Dhrystone benchmark test module
++ *
++ * Copyright (C) 2022 Glider bv
++ */
++
++#include "dhry.h"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/mutex.h>
++#include <linux/smp.h>
++
++#define DHRY_VAX	1757
++
++static int dhry_run_set(const char *val, const struct kernel_param *kp);
++static const struct kernel_param_ops run_ops = {
++	.flags = KERNEL_PARAM_OPS_FL_NOARG,
++	.set = dhry_run_set,
++};
++static bool dhry_run;
++module_param_cb(run, &run_ops, &dhry_run, 0200);
++MODULE_PARM_DESC(run, "Run the test (default: false)");
++
++static int iterations = -1;
++module_param(iterations, int, 0644);
++MODULE_PARM_DESC(iterations,
++		"Number of iterations through the benchmark (default: auto)");
++
++static void dhry_benchmark(void)
++{
++	int i, n;
++
++	if (iterations > 0) {
++		n = dhry(iterations);
++		goto report;
++	}
++
++	for (i = DHRY_VAX; i > 0; i <<= 1) {
++		n = dhry(i);
++		if (n != -EAGAIN)
++			break;
++	}
++
++report:
++	if (n >= 0)
++		pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n",
++			smp_processor_id(), n, n / DHRY_VAX);
++	else if (n == -EAGAIN)
++		pr_err("Please increase the number of iterations\n");
++	else
++		pr_err("Dhrystone benchmark failed error %pe\n", ERR_PTR(n));
++}
++
++static int dhry_run_set(const char *val, const struct kernel_param *kp)
++{
++	int ret;
++
++	if (val) {
++		ret = param_set_bool(val, kp);
++		if (ret)
++			return ret;
++	} else {
++		dhry_run = true;
++	}
++
++	if (dhry_run && system_state == SYSTEM_RUNNING)
++		dhry_benchmark();
++
++	return 0;
++}
++
++static int __init dhry_init(void)
++{
++	if (dhry_run)
++		dhry_benchmark();
++
++	return 0;
++}
++module_init(dhry_init);
++
++MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
++MODULE_LICENSE("GPL");
+-- 
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index 23bf73b..0ed63ca 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -297,6 +297,7 @@
     file://900-v5.9-0001-dt-bindings-Add-multicolor-class-dt-bindings-documen.patch \
     file://900-v5.9-0002-leds-Add-multicolor-ID-to-the-color-ID-list.patch \
     file://900-v5.9-0003-leds-add-RGB-color-option-as-that-is-different-from-.patch \
+    file://999-1900-lib-add-Dhrystone-benchmark-test.patch \
     file://999-2210-v6.1-iio-adc-add-rtq6056-support.patch \
     file://999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch \
     file://999-2311-mtd-spinand-gigadevice-Support-GD5F1GQ5UExxG.patch \
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 8f5f37b..8026921 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
@@ -1165,9 +1165,24 @@
 #define NEXTHDR_IPIP 4
 #endif
 
+#define UDF_PINGPONG_IFIDX GENMASK(3, 0)
+#define UDF_HNAT_PRE_FILLED BIT(4)
+
 extern const struct of_device_id of_hnat_match[];
 extern struct mtk_hnat *hnat_priv;
 
+static inline int is_hnat_pre_filled(struct foe_entry *entry)
+{
+	u32 udf = 0;
+
+	if (IS_IPV4_GRP(entry))
+		udf = entry->ipv4_hnapt.act_dp;
+	else
+		udf = entry->ipv6_5t_route.act_dp;
+
+	return !!(udf & UDF_HNAT_PRE_FILLED);
+}
+
 #if defined(CONFIG_NET_DSA_MT7530)
 u32 hnat_dsa_fill_stag(const struct net_device *netdev,
 		       struct foe_entry *entry,
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 05f4955..ac266b7 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
@@ -491,9 +491,9 @@
 	entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
 
 	if (IS_IPV4_GRP(entry))
-		index = entry->ipv4_hnapt.act_dp;
+		index = entry->ipv4_hnapt.act_dp & UDF_PINGPONG_IFIDX;
 	else
-		index = entry->ipv6_5t_route.act_dp;
+		index = entry->ipv6_5t_route.act_dp & UDF_PINGPONG_IFIDX;
 
 	dev = get_dev_from_index(index);
 	if (!dev) {
@@ -548,9 +548,9 @@
 	if (entry_hnat_is_bound(entry)) {
 		entry->bfib1.state = INVALID;
 		if (IS_IPV4_GRP(entry))
-			entry->ipv4_hnapt.act_dp = 0;
+			entry->ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
 		else
-			entry->ipv6_5t_route.act_dp = 0;
+			entry->ipv6_5t_route.act_dp &= ~UDF_PINGPONG_IFIDX;
 
 		/* clear HWNAT cache */
 		hnat_cache_ebl(1);
@@ -766,6 +766,9 @@
 	if (!skb)
 		goto drop;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	if (!is_ppe_support_type(skb)) {
 		hnat_set_head_frags(state, skb, 1, hnat_set_alg);
 		return NF_ACCEPT;
@@ -831,6 +834,9 @@
 	if (!skb)
 		goto drop;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	if (!is_ppe_support_type(skb)) {
 		hnat_set_head_frags(state, skb, 1, hnat_set_alg);
 		return NF_ACCEPT;
@@ -894,6 +900,9 @@
 	if (!skb)
 		goto drop;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	if (IS_HQOS_MODE && hnat_priv->data->whnat) {
 		veth = (struct vlan_ethhdr *)skb_mac_header(skb);
 
@@ -1222,6 +1231,9 @@
 	if (!hnat_priv->data->mcast && is_multicast_ether_addr(eth->h_dest))
 		return 0;
 
+	if (whnat && is_hnat_pre_filled(foe))
+		return 0;
+
 	entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
 	entry.bfib1.state = foe->udib1.state;
 
@@ -1637,7 +1649,8 @@
 		if (mape_toggle && mape == 1) {
 			gmac = NR_PDMA_PORT;
 			/* Set act_dp = wan_dev */
-			entry.ipv4_hnapt.act_dp = dev->ifindex;
+			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;
 		}
@@ -1659,10 +1672,13 @@
 		 * Current setting is PDMA RX.
 		 */
 		gmac = NR_PDMA_PORT;
-		if (IS_IPV4_GRP(foe))
-			entry.ipv4_hnapt.act_dp = dev->ifindex;
-		else
-			entry.ipv6_5t_route.act_dp = dev->ifindex;
+		if (IS_IPV4_GRP(foe)) {
+			entry.ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
+			entry.ipv4_hnapt.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
+		} else {
+			entry.ipv6_5t_route.act_dp &= ~UDF_PINGPONG_IFIDX;
+			entry.ipv6_5t_route.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
+		}
 	} else {
 		printk_ratelimited(KERN_WARNING
 					"Unknown case of dp, iif=%x --> %s\n",
@@ -1780,6 +1796,11 @@
 	if (!whnat) {
 		entry.bfib1.ttl = 1;
 		entry.bfib1.state = BIND;
+	} else {
+		if (IS_IPV4_GRP(foe))
+			entry.ipv4_hnapt.act_dp |= UDF_HNAT_PRE_FILLED;
+		else
+			entry.ipv6_5t_route.act_dp |= UDF_HNAT_PRE_FILLED;
 	}
 
 	wmb();
@@ -1791,8 +1812,6 @@
 		memset(&hnat_priv->acct[skb_hnat_ppe(skb)][skb_hnat_entry(skb)],
 		       0, sizeof(struct mib_entry));
 
-	skb_hnat_filled(skb) = HNAT_INFO_FILLED;
-
 	return 0;
 }
 
@@ -1802,7 +1821,7 @@
 	struct ethhdr *eth;
 	struct hnat_bind_info_blk bfib1_tx;
 
-	if (skb_hnat_alg(skb) || !is_hnat_info_filled(skb) ||
+	if (skb_hnat_alg(skb) ||
 	    !is_magic_tag_valid(skb) || !IS_SPACE_AVAILABLE_HEAD(skb))
 		return NF_ACCEPT;
 
@@ -1833,6 +1852,9 @@
 	if (skb_hnat_reason(skb) != HIT_UNBIND_RATE_REACH)
 		return NF_ACCEPT;
 
+	if (!is_hnat_pre_filled(entry))
+		return NF_ACCEPT;
+
 	eth = eth_hdr(skb);
 	memcpy(&bfib1_tx, &entry->bfib1, sizeof(entry->bfib1));
 
@@ -2017,6 +2039,11 @@
 	wmb();
 	memcpy(&entry->bfib1, &bfib1_tx, sizeof(bfib1_tx));
 
+	if (IS_IPV4_GRP(entry))
+		entry->ipv4_hnapt.act_dp &= ~UDF_HNAT_PRE_FILLED;
+	else
+		entry->ipv6_5t_route.act_dp &= ~UDF_HNAT_PRE_FILLED;
+
 	return NF_ACCEPT;
 }
 
@@ -2028,7 +2055,6 @@
 	}
 
 	skb_hnat_alg(skb) = 0;
-	skb_hnat_filled(skb) = 0;
 	skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
 
 	if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
@@ -2568,6 +2594,9 @@
 	const struct tcpudphdr *pptr;
 	int udp = 0;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	if (unlikely(!skb_hnat_is_hashed(skb)))
 		return NF_ACCEPT;
 
@@ -2690,6 +2719,9 @@
 	if (!skb)
 		goto drop;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	veth = (struct vlan_ethhdr *)skb_mac_header(skb);
 
 	if (IS_HQOS_MODE && eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
@@ -2737,6 +2769,9 @@
 	if (!skb)
 		goto drop;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	post_routing_print(skb, state->in, state->out, __func__);
 
 	if (!mtk_hnat_nf_post_routing(skb, state->out, 0, __func__))
@@ -2763,6 +2798,9 @@
 	struct foe_entry *entry;
 	struct iphdr *iph;
 
+	if (!is_magic_tag_valid(skb))
+		return NF_ACCEPT;
+
 	if (!skb_hnat_is_hashed(skb))
 		return NF_ACCEPT;
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
index d9eba8d..800c821 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
@@ -85,7 +85,6 @@
 #define HAS_HQOS_MAGIC_TAG(skb) (qos_toggle && skb->protocol == HQOS_MAGIC_TAG)
 
 #define HNAT_MAGIC_TAG 0x6789
-#define HNAT_INFO_FILLED 0x7
 #define WIFI_INFO_LEN 6
 #define FOE_INFO_LEN (10 + WIFI_INFO_LEN)
 #define IS_SPACE_AVAILABLE_HEAD(skb)                                           \
@@ -136,7 +135,6 @@
 #define clr_from_extge(skb) (HNAT_SKB_CB2(skb)->magic = 0x0)
 #define set_to_ppe(skb) (HNAT_SKB_CB2(skb)->magic = 0x78681415)
 #define is_from_extge(skb) (HNAT_SKB_CB2(skb)->magic == 0x78786688)
-#define is_hnat_info_filled(skb) (skb_hnat_filled(skb) == HNAT_INFO_FILLED)
 #define is_magic_tag_valid(skb) (skb_hnat_magic_tag(skb) == HNAT_MAGIC_TAG)
 #define set_from_mape(skb) (HNAT_SKB_CB2(skb)->magic = 0x78787788)
 #define is_from_mape(skb) (HNAT_SKB_CB2(skb)->magic == 0x78787788)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
index 80d5d9f..59aa655 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
@@ -491,6 +491,7 @@
 CONFIG_SYSCTL_EXCEPTION_TRACE=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+# CONFIG_TEST_DHRY is not set
 CONFIG_THERMAL=y
 CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
 CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index 47252dd..cb07304 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -469,6 +469,7 @@
 CONFIG_SYSCTL_EXCEPTION_TRACE=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+# CONFIG_TEST_DHRY is not set
 CONFIG_THERMAL=y
 CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
 CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch
index bccc43e..6d1273c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-wed3-support.patch
@@ -13,7 +13,7 @@
  drivers/net/ethernet/mediatek/mtk_ppe.c       |   17 +-
  drivers/net/ethernet/mediatek/mtk_ppe.h       |    2 +-
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |   13 +-
- drivers/net/ethernet/mediatek/mtk_wed.c       | 1164 +++++++++++++----
+ drivers/net/ethernet/mediatek/mtk_wed.c       | 1174 +++++++++++++----
  drivers/net/ethernet/mediatek/mtk_wed.h       |   25 +-
  .../net/ethernet/mediatek/mtk_wed_debugfs.c   |  584 ++++++++-
  drivers/net/ethernet/mediatek/mtk_wed_mcu.c   |   13 +-
@@ -301,7 +301,7 @@
 index a9feaed..70e8377 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -605,9 +605,12 @@
+@@ -600,9 +600,12 @@
  #define RX_DMA_SPORT_MASK       0x7
  #define RX_DMA_SPORT_MASK_V2    0xf
  
@@ -1018,7 +1018,7 @@
 -#define MTK_WFMDA_RX_DMA_EN 	BIT(2)
 +	if (!mtk_wed_get_rx_capa(dev))
 +		return 0;
-+
+ 
 +	wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM,
 +		FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128));
 +
@@ -1035,7 +1035,7 @@
 +
 +	return 0;
 +}
- 
++
 +static int
 +mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev,
 +			   struct mtk_wed_ring *ring)
@@ -1233,7 +1233,15 @@
  		wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
  		wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
  	}
-@@ -677,13 +1027,21 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
+@@ -665,6 +1015,7 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+ 	wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+ }
+ 
++#define IRQ_MASK_APMCU		0x1000301c
+ static void
+ mtk_wed_deinit(struct mtk_wed_device *dev)
+ {
+@@ -677,13 +1028,31 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
  		MTK_WED_CTRL_WED_TX_BM_EN |
  		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
  
@@ -1247,16 +1255,26 @@
  		MTK_WED_CTRL_RX_RRO_QM_EN);
 +
 +	if (dev->hw->version == 3) {
++		unsigned long addr;
++		u32 value;
++
 +		wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
 +		wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_PAO);
 +		wed_clr(dev, MTK_WED_PCIE_INT_CTRL,
 +			MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
 +			MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER);
++
++		/* clear mask apmcu */
++		addr = (unsigned long)ioremap(IRQ_MASK_APMCU, 4);
++		value = readl((void *)addr);
++		value &= ~0x7;
++		writel(value, (void *)addr);
++		iounmap((void *)addr);
 +	}
  }
  
  static void
-@@ -702,9 +1060,9 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -702,9 +1071,9 @@ mtk_wed_detach(struct mtk_wed_device *dev)
  
  	mtk_wdma_tx_reset(dev);
  
@@ -1268,11 +1286,7 @@
  		mtk_wed_wo_reset(dev);
  		mtk_wed_free_rx_rings(dev);
  		mtk_wed_wo_exit(hw);
-@@ -728,73 +1086,97 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- 	mutex_unlock(&hw_lock);
- }
- 
-+#define IRQ_MASK_APMCU		0x1000301c
+@@ -731,70 +1100,93 @@ mtk_wed_detach(struct mtk_wed_device *dev)
  static void
  mtk_wed_bus_init(struct mtk_wed_device *dev)
  {
@@ -1406,7 +1420,7 @@
  	}
  }
  
-@@ -806,21 +1188,25 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -806,21 +1198,25 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
  	mtk_wed_deinit(dev);
  	mtk_wed_reset(dev, MTK_WED_RESET_WED);
  
@@ -1442,7 +1456,7 @@
  		offset = dev->hw->index ? 0x04000400 : 0;
  		wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
  		wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
-@@ -907,11 +1293,16 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
+@@ -907,11 +1303,16 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
  	} while (1);
  
  	/* configure RX_ROUTE_QM */
@@ -1464,7 +1478,7 @@
  
  	/* enable RX_ROUTE_QM */
  	wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
-@@ -920,23 +1311,45 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
+@@ -920,23 +1321,45 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
  static void
  mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
  {
@@ -1520,7 +1534,7 @@
  
  	wed_w32(dev, MTK_WED_TX_BM_TKID,
  		FIELD_PREP(MTK_WED_TX_BM_TKID_START,
-@@ -946,25 +1359,44 @@ mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
+@@ -946,25 +1369,44 @@ mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
  
  	wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
  
@@ -1576,7 +1590,7 @@
  		wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
  }
  
-@@ -977,7 +1409,26 @@ mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
+@@ -977,7 +1419,26 @@ mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
  
  	wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
  
@@ -1603,7 +1617,7 @@
  	mtk_wed_rro_hw_init(dev);
  	mtk_wed_route_qm_hw_init(dev);
  }
-@@ -991,7 +1442,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+@@ -991,7 +1452,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
  	dev->init_done = true;
  	mtk_wed_set_ext_int(dev, false);
  	mtk_wed_tx_hw_init(dev);
@@ -1612,7 +1626,7 @@
  		mtk_wed_rx_hw_init(dev);
  }
  
-@@ -1015,26 +1466,6 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
+@@ -1015,26 +1476,6 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
  	}
  }
  
@@ -1639,7 +1653,7 @@
  static void
  mtk_wed_rx_reset(struct mtk_wed_device *dev)
  {
-@@ -1133,7 +1564,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1133,7 +1574,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  		mtk_wed_ring_reset(desc, MTK_WED_RX_RING_SIZE, 1, false);
  	}
  
@@ -1648,7 +1662,7 @@
  }
  
  
-@@ -1271,12 +1702,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
+@@ -1271,12 +1712,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
  		int idx, int size, bool reset)
  {
  	struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
@@ -1665,7 +1679,7 @@
  	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
  		 wdma->desc_phys);
  	wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1296,12 +1730,31 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
+@@ -1296,12 +1740,31 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
  	int idx, int size, bool reset)
  {
  	struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
@@ -1698,7 +1712,7 @@
  	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
  		 wdma->desc_phys);
  	wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1312,7 +1765,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
+@@ -1312,7 +1775,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
  		 MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
  	if (reset)
  		mtk_wed_ring_reset(wdma->desc, MTK_WED_WDMA_RING_SIZE,
@@ -1707,7 +1721,7 @@
  	if (idx == 0)  {
  		wed_w32(dev, MTK_WED_WDMA_RING_TX
  			+ MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-@@ -1395,7 +1848,7 @@ mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
+@@ -1395,7 +1858,7 @@ mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
  {
  	struct mtk_wed_wo *wo = dev->hw->wed_wo;
  
@@ -1716,7 +1730,7 @@
  		return 0;
  
  	return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
-@@ -1420,13 +1873,87 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
+@@ -1420,13 +1883,87 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
  	}
  }
  
@@ -1806,7 +1820,7 @@
  
  	for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
  		if (!dev->tx_wdma[i].desc)
-@@ -1437,7 +1964,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -1437,7 +1974,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
  	mtk_wed_set_int(dev, irq_mask);
  	mtk_wed_set_ext_int(dev, true);
  
@@ -1815,7 +1829,7 @@
  		u32 val;
  
  		val = dev->wlan.wpdma_phys |
-@@ -1448,33 +1975,52 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -1448,33 +1985,52 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
  			val |= BIT(1);
  		val |= BIT(0);
  		regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
@@ -1871,7 +1885,7 @@
  	int ret = 0;
  
  	RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
-@@ -1494,34 +2040,30 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -1494,34 +2050,30 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  		goto out;
  	}
  
@@ -1916,7 +1930,7 @@
  		ret = mtk_wed_rro_alloc(dev);
  		if (ret)
  			goto error;
-@@ -1533,15 +2075,20 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -1533,15 +2085,20 @@ mtk_wed_attach(struct mtk_wed_device *dev)
  	init_completion(&dev->wlan_reset_done);
  	atomic_set(&dev->fe_reset, 0);
  
@@ -1940,7 +1954,7 @@
  out:
  	mutex_unlock(&hw_lock);
  
-@@ -1576,8 +2123,26 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
+@@ -1576,8 +2133,26 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
  	if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
  		return -ENOMEM;
  
@@ -1967,7 +1981,7 @@
  
  	/* WED -> WPDMA */
  	wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
-@@ -1599,7 +2164,7 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -1599,7 +2174,7 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
  	struct mtk_wed_ring *ring = &dev->txfree_ring;
  	int i, idx = 1;
  
@@ -1976,7 +1990,7 @@
  		idx = 0;
  
  	/*
-@@ -1652,6 +2217,129 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
+@@ -1652,6 +2227,129 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
  	return 0;
  }
  
@@ -2106,7 +2120,7 @@
  static u32
  mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
  {
-@@ -1660,6 +2348,8 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
+@@ -1660,6 +2358,8 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
  	val = wed_r32(dev, MTK_WED_EXT_INT_STATUS);
  	wed_w32(dev, MTK_WED_EXT_INT_STATUS, val);
  	val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
@@ -2115,7 +2129,7 @@
  	WARN_RATELIMIT(val, "mtk_wed%d: error status=%08x\n",
  		       dev->hw->index, val);
  
-@@ -1752,6 +2442,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1752,6 +2452,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  		.tx_ring_setup = mtk_wed_tx_ring_setup,
  		.txfree_ring_setup = mtk_wed_txfree_ring_setup,
  		.rx_ring_setup = mtk_wed_rx_ring_setup,
@@ -2125,7 +2139,7 @@
  		.msg_update = mtk_wed_send_msg,
  		.start = mtk_wed_start,
  		.stop = mtk_wed_stop,
-@@ -1763,6 +2456,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1763,6 +2466,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  		.detach = mtk_wed_detach,
  		.setup_tc = mtk_wed_eth_setup_tc,
  		.ppe_check = mtk_wed_ppe_check,
@@ -2133,7 +2147,7 @@
  	};
  	struct device_node *eth_np = eth->dev->of_node;
  	struct platform_device *pdev;
-@@ -1802,9 +2496,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1802,9 +2506,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  	hw->wdma_phy = wdma_phy;
  	hw->index = index;
  	hw->irq = irq;
@@ -2146,7 +2160,7 @@
  		hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
  							     "mediatek,pcie-mirror");
  		hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
-@@ -1819,7 +2514,6 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1819,7 +2524,6 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
  			regmap_write(hw->mirror, 0, 0);
  			regmap_write(hw->mirror, 4, 0);
  		}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch
index 3837d8d..ef09f35 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mtk-wed-add-wed3-ser-support.patch
@@ -153,7 +153,7 @@
  			if (mtk_wed_get_rx_capa(dev)) {
  				wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
  					MTK_WED_WPDMA_RX_D_PREF_EN |
-@@ -1477,13 +1580,30 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1487,13 +1590,30 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
  			     &state, sizeof(state), true);
  
@@ -184,7 +184,7 @@
  		wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
  			MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
  			MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
-@@ -1511,6 +1631,24 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1521,6 +1641,24 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  		wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
  	}
  
@@ -209,7 +209,7 @@
  	/* reset route qm */
  	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
  	busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-@@ -1518,8 +1656,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1528,8 +1666,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  	if (busy) {
  		mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
  	} else {
@@ -225,7 +225,7 @@
  	}
  
  	/* reset tx wdma */
-@@ -1527,8 +1670,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1537,8 +1680,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  
  	/* reset tx wdma drv */
  	wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
@@ -241,7 +241,7 @@
  	mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
  
  	/* reset wed rx dma */
-@@ -1546,9 +1694,17 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1556,9 +1704,17 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  	/* reset rx bm */
  	wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
  	mtk_wed_poll_busy(dev, MTK_WED_CTRL,
@@ -260,7 +260,7 @@
  	/* wo change to enable state */
  	state = WO_STATE_ENABLE;
  	mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-@@ -1565,6 +1721,9 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1575,6 +1731,9 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
  	}
  
  	mtk_wed_free_rx_buffer(dev);
@@ -270,7 +270,7 @@
  }
  
  
-@@ -1598,18 +1757,40 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1608,18 +1767,40 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  
  	/* 2. Reset WDMA Rx DMA/Driver_Engine */
  	busy = !!mtk_wdma_rx_reset(dev);
@@ -314,7 +314,7 @@
  		wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
  
  		wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-@@ -1624,9 +1805,15 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1634,9 +1815,15 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  		MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
  
  	for (i = 0; i < 100; i++) {
@@ -333,7 +333,7 @@
  	}
  	mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
  
-@@ -1635,18 +1822,20 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1645,18 +1832,20 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  
  	/* 4. Reset WED WPDMA Tx Driver Engine */
  	busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
@@ -356,7 +356,7 @@
  	} else {
  		wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
  			MTK_WED_WPDMA_RESET_IDX_TX |
-@@ -1659,7 +1848,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1669,7 +1858,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
  		}
  	}
  
@@ -371,7 +371,7 @@
  		dev->init_done = false;
  		mtk_wed_rx_reset(dev);
  	}
-@@ -1874,7 +2069,7 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
+@@ -1884,7 +2079,7 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
  }
  
  static void
@@ -380,7 +380,7 @@
  {
  	int idx, ret;
  
-@@ -1884,6 +2079,11 @@ mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -1894,6 +2089,11 @@ mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
  	if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
  		return;